从尾到头打印链表(Offer 06、07)
2023-10-29 04:32:11
如何替换字符串中的空格并从尾到头打印链表
1. 概述
在编程面试中,经常会遇到一些经典的算法问题,例如替换字符串中的空格和从尾到头打印链表。本文将详细介绍这两种问题的解决方案,并提供一些扩展思考。
2. 替换字符串中的空格
2.1 问题
给定一个字符串 s,请将字符串中的每个空格替换成 "%20"。
2.2 解决方案
方法 1:使用 StringBuilder
最简单的方法是使用 StringBuilder 类。我们可以遍历字符串,并将每个空格字符替换为 "%20"。以下是代码示例:
public String replaceSpaces(String s) {
if (s == null || s.length() == 0) {
return "";
}
StringBuilder sb = new StringBuilder();
for (char c : s.toCharArray()) {
if (c == ' ') {
sb.append("%20");
} else {
sb.append(c);
}
}
return sb.toString();
}
方法 2:使用正则表达式
另一种方法是使用正则表达式。正则表达式可以匹配字符串中的特定模式,并对其进行替换。以下是使用正则表达式的代码示例:
public String replaceSpaces(String s) {
return s.replaceAll(" ", "%20");
}
3. 从尾到头打印链表
3.1 问题
给定一个链表,请从尾到头打印该链表的每个节点的值。
3.2 解决方案
方法 1:使用栈
我们可以使用栈来解决这个问题。栈是一种先进后出的数据结构。我们可以遍历链表,并把每个节点的值压入栈中。然后,我们可以依次弹出栈中的元素,并打印其值。以下是代码示例:
public List<Integer> printLinkedListFromTailToHead(ListNode head) {
List<Integer> result = new ArrayList<>();
if (head == null) {
return result;
}
Stack<Integer> stack = new Stack<>();
ListNode cur = head;
while (cur != null) {
stack.push(cur.val);
cur = cur.next;
}
while (!stack.isEmpty()) {
result.add(stack.pop());
}
return result;
}
方法 2:递归
我们也可以使用递归来解决这个问题。递归是一种函数调用自身的方法。我们可以递归地遍历链表,并在每次递归调用中将节点的值添加到结果列表中。以下是代码示例:
public List<Integer> printLinkedListFromTailToHead(ListNode head) {
List<Integer> result = new ArrayList<>();
if (head == null) {
return result;
}
result.addAll(printLinkedListFromTailToHead(head.next));
result.add(head.val);
return result;
}
4. 扩展思考
4.1 替换字符串中的空格
- 可以使用 Java 的 String.replace() 方法直接进行替换。
public String replaceSpaces(String s) {
return s.replace(" ", "%20");
}
4.2 从尾到头打印链表
- 可以使用双指针法来解决这个问题。
public List<Integer> printLinkedListFromTailToHead(ListNode head) {
List<Integer> result = new ArrayList<>();
if (head == null) {
return result;
}
ListNode slow = head;
ListNode fast = head;
while (fast != null && fast.next != null) {
slow = slow.next;
fast = fast.next.next;
}
while (slow != null) {
result.add(slow.val);
slow = slow.next;
}
return result;
}
5. 常见问题解答
5.1 为什么使用 StringBuilder 代替 String?
StringBuilder 是一种可变字符串,可以高效地进行字符串拼接。而 String 是不可变的,每次拼接都会创建一个新的字符串对象。使用 StringBuilder 可以避免频繁创建新对象,提高效率。
5.2 为什么使用栈来从尾到头打印链表?
栈是一种先进后出的数据结构,可以方便地实现从尾到头的打印顺序。我们可以将节点的值压入栈中,然后依次弹出栈中的元素进行打印。
5.3 双指针法和递归哪个效率更高?
双指针法和递归的效率都与链表的长度成正比。然而,双指针法在空间复杂度上更优,因为它只需要两个指针变量,而递归需要额外的栈空间。
5.4 可以使用队列来从尾到头打印链表吗?
可以。队列是一种先进先出的数据结构,我们可以将节点的值入队,然后依次出队进行打印。但是,使用队列的效率会比使用栈低,因为队列需要额外的空间来存储节点的顺序。
5.5 如何处理链表中存在环的情况?
如果链表中存在环,那么使用递归和双指针法都会陷入死循环。我们可以使用哈希表来检测环的存在,并根据情况进行处理。