算法练习(1)-字符串/单链表反转
前提:不能借助其它数据结构或一些现成工具类。比如调用StringUtils.reverse(str)完成翻转,或者先入stack再出stack。仅使用最基本的分支/循环来实现最优解法。
一、字符串反转
java中字符串,其实就是一个字符数组,可以用数组的思路,首尾交换即可。
private String reverseString(String str) { char[] arr = str.toCharArray(); for (int i = 0; i < arr.length / 2; i++) { int j = arr.length - i - 1; char temp = arr[j]; arr[j] = arr[i]; arr[i] = temp; } return new String(arr); }
二、单链表反转
2.1 头插法
单链表只能从头节点开始1个个向后查找。这里有一个小技巧:通常会在头部加一个哑节点,不存放任何数据,只是为了方便快速找到头节点。
单链表的测试类如下:
class LinkNode { public String value; public LinkNode next; public LinkNode(String v, LinkNode next) { this.value = v; this.next = next; } } LinkNode buildTestLinkNode() { LinkNode d = new LinkNode("d", null); LinkNode c = new LinkNode("c", d); LinkNode b = new LinkNode("b", c); LinkNode a = new LinkNode("a", b); LinkNode dummy = new LinkNode("dummy", a); return dummy; } void printLinkNode(LinkNode head) { while (head.next != null) { System.out.print(head.value + "->"); head = head.next; } System.out.print(head.value + "\n"); } @Test public void testPrintLinkNode() { printLinkNode(buildTestLinkNode()); }
打印出来为:dummy->a->b->c->d
反转的思路如下:
从第2个有效节点开始,将其从链表中摘下来,然后放到哑节点后面,不断重复这个过程。
@Test public void testReverseLinkNode() { LinkNode dummy = buildTestLinkNode(); printLinkNode(dummy); reverseLinkNode(dummy); } /** * 单链表反转 * @param dummy */ private void reverseLinkNode(LinkNode dummy) { if (dummy == null || dummy.next == null || dummy.next.next == null) { return; } LinkNode prev = dummy.next; LinkNode curr = prev.next; while (true) { prev.next = curr.next; curr.next = dummy.next; dummy.next = curr; curr = prev.next; printLinkNode(dummy); if (curr == null) { break; } } }
输出结果:
dummy->a->b->c->d
dummy->b->a->c->d
dummy->c->b->a->d
dummy->d->c->b->a
2.2 原地翻转
LinkNode prev = null, curr = head, next; while (curr != null) { next = curr.next; curr.next = prev; prev = curr; curr = next; } return prev;
过程就不画了, 建议感兴趣的同学自己在纸上画一画。
2.3 递归法
static LinkNode reverse3(LinkNode curr) { if (curr == null || curr.next == null) { return curr; } //递归调用时,会不停压栈,直到最后节点,然后再一层层返回 //所以使用递归方式,效果上相当于1个个node放到stack,再弹出来 reverse3(curr); curr.next.next = curr; curr.next = null; return curr; }
注:递归法,本质上跟自己弄一个stack,将链表元素1个个压入,再1个个弹出是等效的,只不过递归过程,系统自动会帮我们压栈、出栈。
作者:菩提树下的杨过
出处:http://yjmyzz.cnblogs.com
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
出处:http://yjmyzz.cnblogs.com
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。