算法练习(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
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
浙公网安备 33010602011771号