有序数组的 Two Sum
Input: numbers={2, 7, 11, 15}, target=9
Output: index1=1, index2=2
使用双指针,一个指针指向值较小的元素,一个指针指向值较大的元素。指向较小元素的指针从头向尾遍历,指向较大元素的指针从尾向头遍历。
如果两个指针指向元素的和 sum == target,那么得到要求的结果;
- 如果 sum > target,移动较大的元素,使 sum 变小一些;
- 如果 sum < target,移动较小的元素,使 sum 变大一些。
数组中的元素最多遍历一次,时间复杂度为 O(N)。只使用了两个额外变量,空间复杂度为 O(1)。
class Solution {
public int[] twoSum(int[] numbers, int target) {
int left = 0,right = numbers.length - 1;
while (left < right){
int sum = numbers[left] + numbers[right];
if (sum < target){
left++;
}else if (sum > target){
right--;
}else {
return new int[]{left + 1,right + 1};
}
}
return null;
}
}
两数平方和
class Solution {
public boolean judgeSquareSum(int c) {
//sqrt(double c)方法里传入整数自动向上转型为double类型
int right = (int) Math.sqrt(c);
int left = 0;
while (left <= right){
int ans = left * left + right * right;
if (ans < c) left++;
else if (ans > c) right--;
else return true;
}
return false;
}
}
反转字母串中的元音字母
力扣345
注意 String 是不可变的,不能简单地交换 String 的两个字符
一般遇见字符串问题,能转成字符数组就尽量转(方便);
class Solution {
public String reverseVowels(String s) {
String vowels = "aeiouAEIOU";
//StringBuilder sb = new StringBuilder(s);
char[] chars = s.toCharArray();
int i = 0, j = s.length() - 1;
while (i < j) {
//别忘了添加限制条件 i < j,contains()括号里要求charSequence,也可以 chars[i] + ""
while (!vowels.contains(String.valueOf(chars[i])) && i < j) {
i++;
}
while (!vowels.contains(String.valueOf(chars[j])) && i < j) {
j--;
}
/*char temp = sb.charAt(i);
sb.setCharAt(i, sb.charAt(j));
sb.setCharAt(j, temp);*/
char temp = chars[i];
chars[i] = chars[j];
chars[j] = temp;
i++;
j--;
}
//return sb.toString();
return new String(chars);
}
}
或者一个一个移动
class Solution {
public String reverseVowels(String s) {
String vowels = "aeiouAEIOU";
//StringBuilder sb = new StringBuilder(s);
char[] chars = s.toCharArray();
int i = 0, j = s.length() - 1;
while (i < j) {
if(!vowels.contains(chars[i] + "")) {
i++;
}
else if(!vowels.contains(chars[j] + "")) {
j--;
}
/*char temp = sb.charAt(i);
sb.setCharAt(i, sb.charAt(j));
sb.setCharAt(j, temp);*/
else {
char temp = chars[i];
chars[i] = chars[j];
chars[j] = temp;
i++;
j--;
}
}
//return sb.toString();
return new String(chars);
}
}
回文字符串
Input: "abca"
Output: True
Explanation: You could delete the character 'c'.
class Solution {
public boolean validPalindrome(String s) {
char[] chars = s.toCharArray();
for (int i = 0, j = s.length() - 1;i < j; i++,j--){
if (chars[i] != chars[j]){
return isPalindrome(chars, i + 1, j) || isPalindrome(chars, i, j - 1);
}
}
return true;
}
private boolean isPalindrome(char[] s ,int l ,int r){
while (l < r){
if (s[l++] != s[r--]) return false;
}
return true;
}
}
归并两个有序数组
Input:
nums1 = [1,2,3,0,0,0], m = 3
nums2 = [2,5,6], n = 3
Output: [1,2,2,3,5,6]
- 双指针从后往前
class Solution {
public void merge(int[] nums1, int m, int[] nums2, int n) {
int mergeIndex = m + n - 1;
int index1 = m - 1, index2 = n - 1;
while (index1 >= 0 || index2 >= 0) {
if (index1 < 0) {
nums1[mergeIndex--] = nums2[index2--];
} else if (index2 < 0) {
nums1[mergeIndex--] = nums1[index1--];
} else if (nums1[index1] > nums2[index2]) {
nums1[mergeIndex--] = nums1[index1--];
} else {
nums1[mergeIndex--] = nums2[index2--];
}
}
}
}
或者
class Solution {
public void merge(int[] nums1, int m, int[] nums2, int n) {
int mergeIndex = m + n - 1;
int index1 = m - 1, index2 = n - 1;
while (index1 >= 0 && index2 >= 0) {
/*if (nums1[index1] > nums2[index2]) {
nums1[mergeIndex--] = nums1[index1--];
} else {
nums1[mergeIndex--] = nums2[index2--];
}*/
nums1[mergeIndex--] = nums1[index1] > nums2[index2] ? nums1[index1--] : nums2[index2--];
}
// 表示将 nums2 数组从下标 0 位置开始,拷贝到 nums1 数组中,从下标 0 位置开始,长度为 index2+1
//若是 index2 < 0,说明nums2数组已提前比完,则从nums2数组复制0个长度到nums1数组
System.arraycopy(nums2, 0, nums1, 0, index2 + 1);
}
}
时间复杂度 O(n+m),空间复杂度 O(1)
- 双指针从前往后
class Solution {
public void merge(int[] nums1, int m, int[] nums2, int n) {
int i = 0,j = 0,k = 0;
int[] nums1_copy = Arrays.copyOf(nums1, m);
while (i < m && j < n){
nums1[k++] = nums1_copy[i] < nums2[j] ? nums1_copy[i++] : nums2[j++];
}
if (i < m) System.arraycopy(nums1_copy, i, nums1, i + j, m - i);
if (j < n) System.arraycopy(nums2, j, nums1, i + j, n - j);
}
}
时间复杂度 O(n + m),空间复杂度 O(m)
环形链表
- 快慢指针
我们可以假设有a和b两个指针,一个慢一个快,如果链表是有环状的,那么走的快的那个指针迟早会跟慢指针重合的
public class Solution {
public boolean hasCycle(ListNode head) {
if (head == null || head.next == null) return false;
ListNode slow = head,fast = head.next;
while (fast != null && fast.next != null){
if (slow == fast){
return true;
}
slow = slow.next;
fast = fast.next.next;
}
return false;
}
}
或者
public class Solution {
public boolean hasCycle(ListNode head) {
if (head == null || head.next == null) return false;
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;
}
}
下面这种的思想其实就是环形链表不存在尽头, 但只用一个指针遇到真正的环形链表会陷入死循环
例如:
while(head != null){
head = head.next;
if(head == null) return false;
}
所以采用双指针
public class Solution {
public boolean hasCycle(ListNode head) {
if (head == null || head.next == null) return false;
ListNode slow = head,fast = head.next;
while (slow != fast){
if (fast == null || fast.next == null){
return false;
}
slow = slow.next;
fast = fast.next.next;
}
return true;
}
}
时间复杂度 O(n),空间复杂度 O(1)
- 哈希表
public class Solution {
public boolean hasCycle(ListNode head) {
if (head == null || head.next == null) return false;
Set<ListNode> hashset = new HashSet<>();
while (head != null){
if (hashset.contains(head)) return true;
hashset.add(head);
head = head.next;
}
return false;
}
}
时间复杂度O(n),空间复杂度 O(n)
最长子序列
Input:
s = "abpcplea", d = ["ale","apple","monkey","plea"]
Output:
"apple"
题目描述:删除 s 中的一些字符,使得它构成字符串列表 d 中的一个字符串,找出能构成的最长字符串。如果有多个相同长度的结果,返回字典序的最小字符串。
class Solution {
public String findLongestWord(String s, List<String> d) {
String str = "";
for (String s1 : d) {
if (partOfString(s, s1)){
if (str.length() < s1.length() || str.length() == s1.length() && s1.compareTo(str) < 0) str = s1;
}
}
return str;
}
private boolean partOfString(String s1, String s2){
int i = 0,j = 0;
while (i < s1.length() && j < s2.length()){
if (s1.charAt(i) == s2.charAt(j)) j++;
i++;
}
return j == s2.length();
}
}