CS61B 课程笔记(DISC
03 Linked Lists, Arrays)
1. 链表操作
问题
1.1:如何在链表的特定位置插入一个元素?
解答:我们可以遍历链表直到指定的位置,并在那个位置插入一个新节点。如果链表为空,或者位置是
0,则直接在头部插入。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| public void insert(int item, int position) { if (first == null || position == 0) { addFirst(item); return; } IntNode p = first; while (p.next != null && position != 0) { position--; p = p.next; } IntNode newNode = new IntNode(item, p.next); p.next = newNode; }
|
解释:我们首先检查是否需要在头部插入。如果不需要,就遍历链表到达插入位置,创建新节点并插入到链表中。
问题 1.2:如何反转链表?
解答:反转链表的过程是将链表中的指针反转,使所有节点的
next
指针指向它的前一个节点。
1 2 3 4 5 6 7 8 9 10 11
| public void reverse() { IntNode currentNode = null; IntNode nextNode = first; while (nextNode != null) { IntNode nextNextNode = nextNode.next; nextNode.next = currentNode; currentNode = nextNode; nextNode = nextNextNode; } first = currentNode; }
|
解释:我们从链表的头节点开始,逐个反转每个节点的
next
指针,直到遍历完整个链表。最后,将反转后的头节点设置为
first
。
问题
1.3:如何通过递归反转链表?
解答:递归实现反转链表是通过不断调用反转函数直到链表末尾,逐层回溯来反转节点的指针。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| public void reverse() { first = reverse(first); }
private IntNode reverse(IntNode front) { if (front == null || front.next == null) { return front; } else { IntNode lastNode = reverse(front.next); front.next.next = front; front.next = null; return lastNode; } }
|
解释:递归通过不断缩小问题规模来反转链表,直到链表末尾。回溯过程中,逐步反转每个节点的指针。
2. 数组操作
问题
2.1:如何在数组的特定位置插入一个元素?
解答:通过创建一个新数组,将原数组的元素分为两部分:插入位置之前的元素和之后的元素,并将新元素插入到指定位置。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| public static int[] insert(int[] arr, int item, int position) { int[] newArr = new int[arr.length + 1]; position = Math.min(arr.length, position); for (int i = 0; i < position; i++) { newArr[i] = arr[i]; } newArr[position] = item; for (int i = position; i < arr.length; i++) { newArr[i + 1] = arr[i]; } return newArr; }
|
解释:我们首先计算合法的插入位置,之后将原数组的前半部分复制到新数组,再插入新元素,最后复制后半部分。
问题 2.2:如何反转一个数组?
解答:通过交换数组两端的元素,将数组反转。
1 2 3 4 5 6 7 8
| public static void reverse(int[] arr) { int temp; for (int left = 0, int right = arr.length - 1; left < right; left++, right--) { temp = arr[left]; arr[left] = arr[right]; arr[right] = temp; } }
|
解释:我们使用两个指针,分别从数组的两端开始,逐个交换对应位置的元素,直到两个指针相遇。
问题
2.3:如何复制数组中的元素,使每个元素重复它的值对应的次数?
解答:首先计算出结果数组的大小,然后根据每个元素的值,重复该元素多次并存入新数组。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| public static int[] replicate(int[] arr) { int size = 0; for (int item : arr) { size += item; }
int[] result = new int[size]; int i = 0; for (int item : arr) { for (int count = 0; count < item; count++) { result[i++] = item; } } return result; }
|
解释:我们首先通过遍历原数组计算出新数组的总大小,然后根据每个元素的值,在新数组中重复多次,依次填充新数组。