用数组实现一个栈和队列
static class Queue<T> {
private Object[] array;
private int size;
public Queue(int cap) {
array = new Object[cap];
}
public void add(T t) {
array[size++] = t;
}
public T remove() {
if (size == 0) {
return null;
}
T t = (T) array[0];
System.arraycopy(array, 1, array, 0, --size);
array[size] = null;
return t;
}
}
static class Stack<T> {
private Object[] array;
private int size;
public Stack(int cap) {
array = new Object[cap];
}
public void add(T t) {
array[size++] = t;
}
public T remove() {
if (size == 0) {
return null;
}
T t = (T) array[--size];
array[size] = null;
return t;
}
}
盛最多水的容器
leetcode地址
public int maxArea(int[] height) {
int left = 0;
int right = height.length - 1;
int maxArea = 0;
while (left < right) {
int area = Math.min(height[left], height[right]) * (right - left);
if (maxArea < area) {
maxArea = area;
}
if (height[left] > height[right]) {
right--;
} else {
left++;
}
}
return maxArea;
}
移动零
leetcode地址
public void moveZeroes(int[] nums) {
int zeroIndex = 0;
for (int i = 0; i < nums.length; i++) {
if (nums[i] != 0) {
if (zeroIndex < i) {
nums[zeroIndex] = nums[i];
}
zeroIndex++;
}
}
for (int i = zeroIndex; i < nums.length; i++) {
nums[i] = 0;
}
}
爬楼梯问题(斐波拉契数列)
leetcode地址
public int climbStairs(int n) {
int f1 = 1;
int f2 = 2;
if (n == 1) {
return f1;
} else if (n == 2) {
return f2;
}
for (int i = 3; i <= n; i++) {
int temp = f2;
f2 = f1 + f2;
f1 = temp;
}
return f2;
}
两数之和
leetcode地址
public int[] twoSum(int[] nums, int target) {
Map<Integer, Integer> cache = new HashMap<>();
for (int i = 0; i < nums.length; i++) {
if (cache.get(nums[i]) != null) {
return new int[]{cache.get(nums[i]), i};
}
cache.put(target - nums[i], i);
}
return new int[0];
}
三数之和
leetcode地址
public List<List<Integer>> threeSum(int[] nums) {
List<List<Integer>> list = new ArrayList<>();
Arrays.sort(nums);
Map<Integer, Integer> cacheMap = new HashMap<>();
for (int i = 0; i < nums.length; i++) {
cacheMap.put(-nums[i], i);
}
for (int i = 0; i < nums.length; i++) {
if (i > 0 && nums[i] == nums[i - 1]) {
continue;
}
for (int j = i + 1, k = nums.length - 1; j < k; ) {
if (j > i + 1 && nums[j] == nums[j - 1]) {
j++;
continue;
}
if (k < nums.length - 1 && nums[k] == nums[k + 1]) {
k--;
continue;
}
if (nums[i] + nums[j] + nums[k] == 0) {
list.add(Arrays.asList(nums[i], nums[j], nums[k]));
j++;
k--;
} else if (nums[i] + nums[j] + nums[k] > 0) {
k--;
} else {
j++;
}
}
}
return list;
}
链表反转
leetcode地址
public ListNode reverseList(ListNode head) {
ListNode pre = null;
ListNode curr = head;
while (curr != null) {
ListNode next = curr.next;
curr.next = pre;
pre = curr;
curr = next;
}
return pre;
}
public ListNode reverseList(ListNode head) {
if(head==null || head.next==null){
return head;
}
ListNode ret = reverseList(head.next);
head.next.next = head;
head.next = null;
return ret;
}
两两交换链表中的节点
leetcode地址
public ListNode swapPairs(ListNode head) {
if (head == null || head.next == null) {
return head;
}
ListNode next = head.next;
head.next = swapPairs(next.next);
next.next = head;
return next;
}
public ListNode swapPairs(ListNode head) {
ListNode pre = new ListNode(0);
pre.next = head;
ListNode curr = pre;
while (curr.next != null && curr.next.next != null) {
ListNode start = curr.next;
ListNode end = start.next;
start.next = end.next;
end.next = start;
curr.next = end;
curr = start;
}
return pre.next;
}
环形链表
leetcode地址
public boolean hasCycle(ListNode head) {
if (head == null || head.next == null) {
return false;
}
ListNode slow = head;
ListNode fast = head.next;
while (fast != null && fast.next != null) {
if (fast == slow) {
return true;
}
slow = slow.next;
fast = fast.next.next;
}
return false;
}
环形链表 II
leetcode地址
public ListNode detectCycle(ListNode head) {
if (head == null || head.next == null) {
return null;
}
ListNode slow = head;
ListNode fast = head;
while (true) {
if (fast == null || fast.next == null) {
return null;
}
slow = slow.next;
fast = fast.next.next;
if (fast == slow) {
break;
}
}
fast = head;
while (fast != slow) {
slow = slow.next;
fast = fast.next;
}
return fast;
}
k个一组翻转链表
leetcode地址
public ListNode reverseKGroup(ListNode head, int k) {
ListNode temp = head;
ListNode newHeader = head;
ListNode lastGroupTail = null;
while (temp != null) {
ListNode currHead = temp;
int count = 0;
for (; count < k && temp != null; count++) {
temp = temp.next;
}
ListNode pre;
if (count == k) {
pre = reverse(currHead, k);
} else {
pre = currHead;
}
if (lastGroupTail != null) {
lastGroupTail.next = pre;
} else {
newHeader = pre;
}
lastGroupTail = currHead;
}
return newHeader;
}
private ListNode reverse(ListNode head, int k) {
ListNode curr = head, pre = null;
while (curr != null && k-- > 0) {
ListNode next = curr.next;
curr.next = pre;
pre = curr;
curr = next;
}
return pre;
}
删除有序数组中的重复项
lettcode地址
public static int removeDuplicates(int[] nums) {
int n = nums.length;
if (n == 0) {
return 0;
}
int fast = 1, slow = 1;
while (fast < n) {
if (nums[fast] != nums[fast - 1]) {
nums[slow] = nums[fast];
slow++;
}
fast++;
}
return slow;
}
轮转数组
leetcode
public void rotate(int[] nums, int k) {
int n = nums.length;
int[] newArr = new int[n];
for (int i = 0; i < n; ++i) {
newArr[(i + k) % n] = nums[i];
}
System.arraycopy(newArr, 0, nums, 0, n);
}
合并两个有序链表
leetcode
public ListNode mergeTwoLists(ListNode list1, ListNode list2) {
ListNode head = new ListNode(0), curr = head;
while (list1 != null && list2 != null) {
if (list1.val > list2.val) {
curr.next = list2;
list2 = list2.next;
} else {
curr.next = list1;
list1 = list1.next;
}
curr = curr.next;
}
curr.next = list1 == null ? list2 : list1;
return head.next;
}
public ListNode mergeTwoLists(ListNode list1, ListNode list2) {
if (list1 == null) {
return list2;
} else if (list2 == null) {
return list1;
} else if (list1.val < list2.val) {
list1.next = mergeTwoLists(list1.next, list2);
return list1;
} else {
list2.next = mergeTwoLists(list1, list2.next);
return list2;
}
}
合并两个有序的数组
leetcode
public void merge(int[] nums1, int m, int[] nums2, int n) {
int mIndex = 0, nIndex = 0;
while (mIndex < m + n && nIndex < n) {
if (nums1[mIndex] > nums2[nIndex]) {
System.arraycopy(
nums1, mIndex, nums1, mIndex + 1, m + n - mIndex - 1
);
nums1[mIndex] = nums2[nIndex];
nIndex++;
}
mIndex++;
}
for (; nIndex < n; nIndex++) {
nums1[nIndex + m] = nums2[nIndex];
}
}
public void merge(int[] nums1, int m, int[] nums2, int n) {
if (m == 0) {
System.arraycopy(nums2, 0, nums1, 0, m + n);
}
if (n == 0) {
return;
}
int[] sort = new int[m + n];
int sortIndex = 0, mIndex = 0, nIndex = 0
for (; sortIndex < m + n; sortIndex++) {
if (mIndex >= m || nIndex < n && nums1[mIndex] > nums2[nIndex]) {
sort[sortIndex] = nums2[nIndex++];
} else {
sort[sortIndex] = nums1[mIndex++];
}
}
System.arraycopy(sort, 0, nums1, 0, m + n);
}
public void merge(int[] nums1, int m, int[] nums2, int n) {
if (m == 0) {
System.arraycopy(nums2, 0, nums1, 0, m + n);
return;
}
if (n == 0) {
return;
}
int index = m + n - 1, mIndex = m - 1, nIndex = n - 1;
for (; index >= 0; index--) {
if (nIndex < 0 || mIndex >= 0 && nums1[mIndex] > nums2[nIndex]) {
nums1[index] = nums1[mIndex--];
} else {
nums1[index] = nums2[nIndex--];
}
}
}
加一
leetcode
public int[] plusOne(int[] digits) {
for (int i = digits.length - 1; i >= 0; i--) {
if ((digits[i] + 1) % 10 == 0) {
digits[i] = 0;
} else {
digits[i] = digits[i] + 1;
return digits;
}
}
int[] result = new int[digits.length + 1];
result[0] = 1;
return result;
}
总结
- 双指针前后夹逼、双指针步调追踪,常常用于解决数组和链表的问题,一般都会有比较明显的特点,比如有序的数组、乘最多水的容器(优先移动低的方向指针),用双指针来降低时间复杂度
- 使用 map 缓存,常常用于需要二次遍历的地方,可以先缓存起来,然后再次用0(1)的哈希表去找数据