【Code Caprice】Double pointer method to write questions

remove element

Title: 27. Remove Elements - LeetCode

Given an array  nums and a value  val, you need to   remove all elements equal to the value  in placeval  , and return the new length of the removed array.

Fast and slow pointer:

public int removeElement(int[] nums, int val) {
    
    
	int l = 0;
	for (int r = 0; r < nums.length; r++)
		if (nums[r] != val) nums[l++] = nums[r];
	return l;
}

Remove duplicates in sorted array

Topic: 26. Remove duplicates in an ordered array - LeetCode

Given an   array in  ascending ordernums  , please   delete repeated elements  in place so that each element appears only once  , and return the new length of the deleted array. The relative order of elements   should be  consistent  .

Fast and slow pointer:

public int removeDuplicates(int[] nums) {
    
    
	int l = 1;
	for (int r = 1; r < nums.length; r++) 
		if (nums[r] != nums[l - 1]) nums[l++] = nums[r];
	return l;
}

moving zero

Title: 283. Moving Zero - LeetCode

Given an array  nums, write a function to  0 move all to the end of the array while maintaining the relative order of the nonzero elements.

Fast and slow pointer:

class Solution {
    
    
    public void moveZeroes(int[] nums) {
    
    
        for (int l = 0, r = 0; r < nums.length; r++)
            if (nums[r] != 0) swap(nums, l++, r);
    }
    void swap(int[] nums, int i, int j) {
    
    
        nums[i] ^= nums[j];
        nums[j] ^= nums[i];
        nums[i] ^= nums[j];
    }
}

Double pointer without swap:

public void moveZeroes(int[] nums) {
    
    
	int l = 0;
	// 将非 0 元素按顺序放到前面
	for (int r = 0; r < nums.length; r++)
		if (nums[r] != 0) nums[l++] = nums[r];
	// 后面全部赋 0
	while (l < nums.length) nums[l++] = 0;
}

Compare strings with backspace*

Title: 844. Comparing Strings with Backspaces - LeetCode

Given  s and  t two strings, when they are entered into a blank text editor, if they are equal, return  true . # Represents the backspace character.

输入:s = "ab#c", t = "ad#c"
输出:true
解释:s 和 t 都会变成 "ac"。

Restructure a string from front to back:

class Solution {
    
    
    public boolean backspaceCompare(String s, String t) {
    
    
        return getString(s).equals(getString(t));
    }

    public String getString(String s) {
    
    
        StringBuilder sb = new StringBuilder();
        char[] cs = s.toCharArray();
        for (int i = 0; i < cs.length; i++) {
    
    
            if (cs[i] != '#') sb.append(cs[i]);
            else if (sb.length() > 0) sb.deleteCharAt(sb.length() - 1);
        }
        return sb.toString();
    }
}

Restructure a string from back to front:

class Solution {
    
    
    public boolean backspaceCompare(String s, String t) {
    
    
        return getString(s).equals(getString(t));
    }

    private String getString(String s) {
    
    
        StringBuilder sb = new StringBuilder();
        char[] cs = s.toCharArray();
        int size = 0; // '#' 数量
        for (int i = cs.length - 1; i >= 0; i--) {
    
    
            if (cs[i] == '#') size++; 
            else if (size == 0) sb.append(cs[i]); 
            else size--;
        }
        return sb.toString();
    }
}

O(1) space complexity approach: hard. . .

Square of sorted array

Title: 977. Squaring of Sorted Arrays - LeetCode

Given an   array of integers sorted in  non-decreasing ordernums , return   a new array consisting of  the square of each number , also sorted in non-decreasing order  .

输入:nums = [-4,-1,0,3,10]
输出:[0,1,9,16,100]
解释:平方后,数组变为 [16,1,0,9,100]
排序后,数组变为 [0,1,9,16,100]
public int[] sortedSquares(int[] nums) {
    
    
	int[] res = new int[nums.length];
	int l = 0, r = nums.length - 1;
	for (int i = nums.length - 1; i >= 0; i--) {
    
    
		if (nums[l] + nums[r] < 0) {
    
     // 左边绝对值大
			res[i] = nums[l] * nums[l++];
		} else {
    
     // 右边绝对值大
			res[i] = nums[r] * nums[r--];
		}
	}
	return res;
}

reverse string

Title: 344. Reverse a String - LeetCode

Write a function that reverses the input string. The input string  s is given as a character array.

Swap operations using bitwise operations:

public void reverseString(char[] s) {
    
    
	int size = s.length - 1;
	for (int i = 0; i < s.length / 2; i++) {
    
    
		int j = size - i;
		s[i] ^= s[j];
		s[j] ^= s[i];
		s[i] ^= s[j];
	}
}

Generally, the inverted character array can be extracted into a template (this function is often used)

class Solution {
    
    
    public void reverseString(char[] s) {
    
    
        reverse(s, 0, s.length - 1);
    }
	// 反转字符数组
    void reverse(char[] cs, int l, int r) {
    
    
        while (l < r) {
    
    
            cs[l] ^= cs[r];
            cs[r] ^= cs[l];
            cs[l++] ^= cs[r--];
        }
    }
}

replace spaces

Please implement a function to replace  s each space in the string with "%20".

Title: Sword Pointing to Offer 05. Replace spaces - LeetCode

public String replaceSpace(String s) {
    
    
	StringBuilder sb = new StringBuilder();
	for (char c : s.toCharArray()) {
    
    
		if (c != ' ') sb.append(c);
		else sb.append("%20");
	}
	return sb.toString();
}

Reverse linked list: recursion + iteration + head insertion

Topic: 206. Reverse Linked List - LeetCode

Given the head node of the singly linked list  head , please reverse the linked list and return the reversed linked list.

Double pointer:

public ListNode reverseList(ListNode head) {
    
    
	ListNode cur = head, pre = null;
	while (cur != null) {
    
    
		ListNode tmp = cur.next;
		cur.next = pre;
		pre = cur;
		cur = tmp;
	}
	return pre;
}

recursion:

public ListNode reverseList(ListNode head) {
    
    
	if (head == null || head.next == null) return head;
	ListNode node = reverseList(head.next);
	head.next.next = head;
	head.next = null;
	return node;
}

Head interpolation: space O(n)

public ListNode reverseList(ListNode head) {
    
    
	ListNode res = null;
	for (ListNode x = head; x != null; x = x.next)
		res = new ListNode(x.val, res);
	return res;
}

Delete the last Nth node of the linked list*

Topic: 19. Delete the last N node of the linked list - LeetCode

Given a linked list, delete the penultimate  n node of the linked list, and return the head node of the linked list.

Fast and slow pointer:

  • The fast pointer moves n steps first, and then starts to move at the same time as the slow pointer
  • When the fast pointer points to the last node, the slow pointer points to the node to be deleted (the previous node)
public ListNode removeNthFromEnd(ListNode head, int n) {
    
    
	if (head == null || head.next == null) return null;
	ListNode fast = head, slow = head;
	while (n-- > 0) fast = fast.next; // 快指针先走 n 步
	if (fast == null) return head.next; // 删除第一个节点
	while (fast.next != null) {
    
    
		fast = fast.next;
		slow = slow.next;
	}
	slow.next = slow.next.next;
	return head;
}

Fast and slow pointer + virtual head node:

Generally using virtual head nodes does not need to deal with special cases

public ListNode removeNthFromEnd(ListNode head, int n) {
    
    
	ListNode vn = new ListNode(0, head); // 虚拟头节点
	ListNode slow = vn, fast = vn;
	while (n-- > 0) fast = fast.next; // 快指针先走 n 步
	while (fast.next != null) {
    
    
		fast = fast.next;
		slow = slow.next;
	}
	slow.next = slow.next.next;
	return vn.next;
}

recursion:

class Solution {
    
    
    int cur = 0;
    public ListNode removeNthFromEnd(ListNode head, int n) {
    
    
        if (head == null) return null;
        head.next = removeNthFromEnd(head.next, n);
        cur++;
        if (cur == n) return head.next;
        return head;
    }
}

Ring linked list: fast and slow pointer

Topic: 141. Ring Linked List - LeetCode

Given the head node of a linked list  head , determine whether there is a ring in the linked list.

Fast and slow pointer:

public boolean hasCycle(ListNode head) {
    
    
	ListNode slow = head, fast = head;
	while (fast != null && fast.next != null) {
    
    
		slow = slow.next;
		fast = fast.next.next;
		if (slow == fast) return true;
	}
	return false;
}

hash:

public boolean hasCycle(ListNode head) {
    
    
	Set<ListNode> set = new HashSet<>();
	while (head != null && !set.contains(head)) {
    
    
		set.add(head);
		head = head.next;
	}
	return head != null;
}

Ring Linked List II**

Topic: 142. Circular Linked List II - LeetCode

Given the head node of a linked list   head , return the first node where the linked list starts entering the ring. Returns if the linked list is acyclic  null.

Fast and slow pointer judgment ring + find ring entry:

public ListNode detectCycle(ListNode head) {
    
    
	ListNode slow = head, fast = head;
	// 快慢指针判断是否有环
	while (fast != null && fast.next != null) {
    
    
		slow = slow.next;
		fast = fast.next.next;
		if (slow == fast) {
    
     // 有环, 找环的起始点
			fast = head; // 快指针从头开始
			while (fast != slow) {
    
    
				fast = fast.next;
				slow = slow.next;
			}
			return fast;
		}
	}
	return null;
}

hash:

public ListNode detectCycle(ListNode head) {
    
    
	Set<ListNode> set = new HashSet<>();
	while (head != null && !set.contains(head)) {
    
    
		set.add(head);
		head = head.next;
	}
	return head;
}

linked list intersect*

Topic: Interview Question 02.07. Linked List Intersection - LeetCode

Given the sum of the head nodes of two singly linked lists  headA ,  headB please find and return the starting node where the two singly linked lists intersect. If there is no intersection between the two linked lists, return  null .

Double pointer:

public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
    
    
	ListNode curA = headA, curB = headB;
	int lenA = 0, lenB = 0;
	// 求链表 A 的长度
	while (curA != null) {
    
     
		lenA++; 
		curA = curA.next; 
	}
	// 求链表 B 的长度
	while (curB != null) {
    
     
		lenB++; 
		curB = curB.next; 
	}
	curA = headA;
	curB = headB;
	// 链表 A 更长则让 A 多走, B 更长则让 B 多走,保证 A B 从同一位置开始比较
	if (lenA > lenB) for (int i = 0; i < lenA - lenB; i++) curA = curA.next;
	else for (int i = 0; i < lenB - lenA; i++) curB = curB.next;
	// 逐个比较 A 和 B 
	while (curA != null) {
    
    
		if (curA == curB) return curA;
		curA = curA.next;
		curB = curB.next;
	}
	return curA;
}

Clever approach:

  • a goes to b, b goes to a, if there is an intersection point, it will inevitably meet
  • If there is no intersection point, it will end up meeting atnull
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
    
    
	ListNode h1 = headA, h2 = headB;
	while (h1 != h2) {
    
    
		h1 = (h1 == null) ? headB : h1.next;
		h2 = (h2 == null) ? headA : h2.next;
	}
	return h1;
}

hash:

public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
    
    
	Set<ListNode> set = new HashSet<>();
	ListNode p = headA;
	while (p != null) {
    
    
		set.add(p);
		p = p.next;
	}
	p = headB;
	while (p != null) {
    
    
		if (set.contains(p)) return p;
		p = p.next;
	}
	return null;
}

sum of three numbers**

Topic: 15. Sum of Three Numbers - LeetCode

Given an array of integers  nums , determine whether there is a triple  [nums[i], nums[j], nums[k]] that satisfies  i != j, i != k and  j != k , and satisfies at the same time  nums[i] + nums[j] + nums[k] == 0 . Please return all  0 triples whose sum is and are not repeated.

**Note:** The answer cannot contain repeated triplets.

Ideas:

  1. sort array
  2. Define i, j, k three pointers. Traversing i, transforming the problem into finding in the array after inums[j] = nums[k] = -nusm[i]
  3. Pay attention to find while going to heavy
public List<List<Integer>> threeSum(int[] nums) {
    
    
	List<List<Integer>> res = new ArrayList<>();
	int n = nums.length;
	Arrays.sort(nums);
	// 剪枝: 最小的数 > 0 或 最大的数 < 0, 不可能和为 0
	if (nums[0] > 0 || nums[n - 1] < 0) return res;
	// 转化成两数之和: 寻找 nums[j] + nums[k] = -nums[i]
	for (int i = 0; i < n; i++) {
    
    
		 if (nums[i] > 0) break; // 不可能找到和为 0 的三元组
		 if (i > 0 && nums[i] == nums[i - 1]) continue; // 去重
		 // 两数之和寻找方法: 双指针, j 从前开始, k 从后开始
		 int j = i + 1, k = n - 1, target = -nums[i];
		 while (j < k) {
    
    
			if (nums[j] + nums[k] < target) j++;
			else if (nums[j] + nums[k] > target) k--;
			else {
    
    
				res.add(Arrays.asList(nums[i], nums[j], nums[k]));
				while (j < k && nums[j] == nums[j + 1]) j++; // 去重
				while (j < k && nums[k] == nums[k - 1]) k--; // 去重
				j++;
				k--;
			}
		 }
	}
	return res;
}

sum of four numbers

Topic: 18. Sum of Four Numbers - LeetCode

You are given an  n array of integers  nums , and a target value  target . Please find and return the quadruples  that meet all the following conditions and are not repeated [nums[a], nums[b], nums[c], nums[d]] (if the two quadruple elements correspond to each other, the two quadruples are considered to be repeated):

  • 0 <= a, b, c, d < n
  • a, b, c and  d are different from each other
  • nums[a] + nums[b] + nums[c] + nums[d] == target

You can return answers in  any order  .

public List<List<Integer>> fourSum(int[] nums, int target) {
    
    
	List<List<Integer>> res = new ArrayList<>();
	int n = nums.length;
	if (n < 4) return res;
	Arrays.sort(nums);
	// 处理越界的情况: 正 + 正 = 负 
	if (nums[0] > 0 && target <= 0 || nums[n - 1] < 0 && target >= 0) return res;

	for (int i = 0; i < n - 3; i++) {
    
    
		if (i > 0 && nums[i] == nums[i - 1]) continue; // 去重
		// 剪枝: 当前情况的最小和 > target 或 最大和 < target
		if ((long) nums[i] + nums[i + 1] + nums[i + 2] + nums[i + 3] > target) break;
		if ((long) nums[i] + nums[n - 3] + nums[n - 2] + nums[n - 1] < target) continue;
		for (int j = i + 1; j < n - 2; j++) {
    
    
			if (j > i + 1 && nums[j] == nums[j - 1]) continue; // 去重
			// 剪枝: 当前情况的最小和 > target 或 最大和 < target
			if ((long) nums[i] + nums[j] + nums[j + 1] + nums[j + 2] > target) break;
			if ((long) nums[i] + nums[j] + nums[n - 2] + nums[n - 1] < target) continue;
			// 两数之和
			int k = j + 1, l = n - 1;
			while (k < l) {
    
    
				int sum = nums[i] + nums[j] + nums[k] + nums[l];
				if (sum < target) k++;
				else if (sum > target) l--;
				else {
    
    
					res.add(Arrays.asList(nums[i], nums[j], nums[k], nums[l]));
					while (k < l && nums[k] == nums[k + 1]) k++; // 去重
					while (k < l && nums[l] == nums[l - 1]) l--; // 去重
					k++;
					l--;
				}
			}
		}
	}
	return res;
}

Dividing line-----

Longest substring without repeating characters*

Topic: 3. The longest substring without repeating characters - LeetCode

Given a string  s , find  the length of the longest substring that does not contain repeated characters  .

Double pointer:

public int lengthOfLongestSubstring(String s) {
    
    
	char[] cs = s.toCharArray();
	int[] map = new int[128]; // 字符 与 出现次数
	int res = 0;
	for (int l = 0, r = 0; r < cs.length; r++) {
    
    
		map[cs[r]]++; // 访问字符
		while (map[cs[r]] > 1) map[cs[l++]]--;
		res = Math.max(res, r - l + 1);
	}
	return res;
}

Guess you like

Origin blog.csdn.net/weixin_43734095/article/details/126733734