双指针:
双指针主要用于遍历数组,两个指针指向不同的元素,从而协同完成任务。
Input: numbers={2, 7, 11, 15}, target=9
Output: index1=1, index2=2
题目描述:在有序整数数组中,找到两个和为目标值得元素并封装成数组返回。
思路:
使用双指针,一个指针指向值较小的元素,一个指针指向值较大的元素。指向较小元素的指针从头向尾遍历,指向较大元素的指针从尾向头遍历。
- 如果两个指针指向元素的和 sum == target,那么得到要求的结果;
- 如果 sum > target,移动较大的元素,使 sum 变小一些;
- 如果 sum < target,移动较小的元素,使 sum 变大一些。
1 private static int[] find(int[] arr, int target) { 2 int low = 0; 3 int high = arr.length - 1; 4 int[] newArr = new int[2]; 5 while (low < high) { 6 if (arr[low] + arr[high] < target) { 7 low++; 8 } else if (arr[low] + arr[high] > target) { 9 high--; 10 } else { 11 return new int[] { arr[low], arr[high] }; 12 } 13 } 14 return null; 15 }
Input: 5
Output: Tru
Explanation: 1 * 1 + 2 * 2 = 5
题目描述:设计一个函数,实现:判断输入的一个数是否为两个数的平方和。
思路:从数学上看,左指针的平方加上右指针的平方要等于target。则左指针选从0开始,右指针选数学上(int) Math.sqrt(c),即向下取整。
1 private static boolean find(int c) { 2 int low = 0; 3 int high = (int) Math.sqrt(c); 4 while (low <= high) { 5 int temp = low * low + high * high; 6 if (temp < c) 7 low++; 8 else if (temp > c) 9 high--; 10 else 11 return true; 12 } 13 return false; 14 }
3.反转字符串中的元音字符
题目描述:反转字符串中的元音字符串。
例子:Given s = "leetcode", return "leotcede".
思路:使用双指针指向待反转的两个元音字符,一个指针从头向尾遍历,一个指针从尾到头遍历。
1 public class test3 { 2 final static List<Character> list = new ArrayList<>( 3 Arrays.asList('a', 'e', 'i', 'o', 'u', 'A', 'E', 'I', 'O', 'U'));//全局变量 4 5 public static void main(String[] args) { 6 String string = "aeiouhhhae"; 7 System.out.println(reverse(string)); 8 } 9 10 private static String reverse(String string) { 11 char[] newArr = new char[string.length()]; 12 int low = 0; 13 int high = string.length() - 1; 14 while (low <= high) { 15 char a = string.charAt(low); 16 char b = string.charAt(high); 17 18 if (!list.contains(a)) { 19 newArr[low] = a; 20 low++; 21 } else if (!list.contains(b)) { 22 newArr[high] = b; 23 high--; 24 } else { 25 char temp = newArr[low]; 26 newArr[low++] = b; 27 newArr[high--] = a; 28 } 29 } 30 return new String(newArr); 31 } 32 }
4.回文字符串
题目描述:对于字符串,判断是否是回文串,可以最多删掉一个字符
例子:
Input: "abca"
Output: True
Explanation: You could delete the character 'c'.
思路:当第一次用左右指针遍历时碰到不相等的情况时,调用函数,在该函数中只要不是回文串就返回false
1 private static boolean find(String str) { 2 int i = -1, j = str.length(); 3 while (++i < --j) { 4 if (str.charAt(i) != str.charAt(j)) { 5 return isFind(str, i + 1, j) || isFind(str, i, j - 1); 6 } 7 } 8 return true; 9 10 } 11 12 private static boolean isFind(String str, int i, int j) { 13 while (i++ < j--) { 14 if (str.charAt(i) != str.charAt(j)) 15 return false; 16 } 17 return true; 18 }
5.归并两个有序数组
Input:
nums1 = [1,2,3,0,0,0], m = 3
nums2 = [2,5,6], n = 3
Output: [1,2,2,3,5,6]
题目描述:把归并结果存到第一个数组上。
需要从尾开始遍历,否则在 nums1 上归并得到的值会覆盖还未进行归并比较的值。
1 private static int[] find(int[] nums1, int n, int[] nums2, int m) { 2 3 int i = n - 1, j = m - 1; 4 int index = nums1.length - 1; 5 while (i >= 0 || j >= 0) { 6 if (i == -1) { 7 nums1[index--] = nums2[j--]; 8 } else if (j == -1) { 9 nums1[index--] = nums1[i--]; 10 } else 11 nums1[index--] = nums1[i] > nums2[j] ? nums1[i--] : nums2[j--]; 12 } 13 return nums1; 14 15 }
6.判断链表是否存在环
题目描述:判断链表是否存在环
思路:使用双指针,一个指针每次移动一个节点,一个指针每次移动两个节点,如果存在环,那么这两个指针一定会相遇。就像两个人不同速度在操场上跑步必定会相遇一样。
1 private static boolean find(node head) { 2 if (head == null) 3 return true; 4 node temp1 = head; 5 node temp2 = head; 6 while (temp1 != null && temp2 != null && temp2.next != null) { 7 temp1 = temp1.next; 8 temp2 = temp2.next.next; 9 if (temp1 == temp2) 10 return true; 11 } 12 return false; 13 14 }
7.最长子序列
Input:
s = "abpcplea", d = ["ale","apple","monkey","plea"]
Output:
"apple"
题目描述:删除 s 中的一些字符,使得它构成字符串列表 d 中的一个字符串,找出能构成的最长字符串。如果有多个相同长度的结果,返回字典序的最小字符串。
1 private static String findLongestWord(String s, List<String> d) { 2 String longestWord = ""; 3 for (String target : d) {//遍历list,判断元素与string 是否满足要求。 4 int l1 = longestWord.length(), l2 = target.length(); 5 if (l1 > l2 || (l1 == l2 && longestWord.compareTo(target) < 0)) { 6 continue; 7 } 8 if (isValid(s, target)) { 9 longestWord = target;//满足要求 10 } 11 } 12 return longestWord; 13 } 14 15 16 /** 17 * 判断一个字符串删除一些字符后是否能与后一个字符串相等 18 * @param s 19 * @param target 20 * @return 21 */ 22 private static boolean isValid(String s, String target) { 23 int i = 0, j = 0; 24 while (i < s.length() && j < target.length()) { 25 if (s.charAt(i) == target.charAt(j)) { 26 j++; 27 } 28 i++; 29 } 30 return j == target.length(); 31 } 32 }