3. 找出数组中重复的数字
在一个长度为 n 的数组里的所有数字都在 0 到 n-1 范围内,其中某些数字是重复的。但不知道有几个数字重复,也不知道每个数字重复几次。找出数组中任意一个重复的数字
首先,可以考虑用HashSet来保存数字,时间复杂度O(n), 空间复杂度O(n)
注意到数字范围特特性,和题目中的任意一个重复的数字
如果无重复,数字可以按照顺序存储的(基数),如果重复,存储过程中一定会产生冲突。这样,一个for循环遍历,while判断重复
public static boolean duplicated(int[] arr) {
if (arr == null) return false;
for (int i = 0; i < arr.length; i++) {
while (i != arr[i]) {
if (arr[i] == arr[arr[i]]) {
System.out.println(arr[i]);
return true;
} else {
swap(arr, i, arr[i]);
}
}
}
return false;
}
}
5. 替换空格
把字符串中的每个空格替换成"%20". 例如,输入"we are happy",则输出"we%20are%20happy"
- 新建一个数组,依次遍历字符,空间复杂度O(n)
- 原地修改,先遍历,碰到空格则增加长度。从后向前插入字符,p1指向原字符串末尾,p2指向当前末尾。分两种情况处理,p1碰到字符和非字符
public static String replace2(StringBuffer arr) {
if (arr == null) return null;
int p1 = arr.length() - 1;
for (int i = 0; i <= p1; i++) {
if (arr.charAt(i) == ' ') {
arr.append(" ");
}
}
int p2 = arr.length() - 1;
while (p1 < p2) {
if (arr.charAt(p1) != ' ') {
arr.setCharAt(p2--, arr.charAt(p1--));
} else {
p1--;
arr.setCharAt(p2--, '0');
arr.setCharAt(p2--, '2');
arr.setCharAt(p2--, '%');
}
}
return arr.toString();
}
6. 从尾到头打印链表
-
逆置链表,再顺序打印,修改了链表的状态
public static Node reverse(Node head) { if (head == null || head.next == null) return head; Node curr = head.next; head.next = null; Node prep = head; Node next = curr.next; while (curr.next != null) { next = curr.next; curr.next = prep; prep = curr; curr = next; } curr.next = prep; return curr; }
-
由于栈先进后出的特性,遍历链表入栈,出栈打印。 不改变原链表结构,空间复杂度O(n)
public static void print1(Node head) {
Stack<Node> stack = new Stack<>();
while (head != null) {
stack.push(head);
head = head.next;
}
while (!stack.isEmpty()) {
System.out.println(stack.pop().val + " ");
}
}
- 借助系统调用栈,递归实现
public static void print2(Node head) {
if (head == null)
return;
if (head.next != null) {
print2(head.next);
}
System.out.println(head.val + " ");
}