本文是对数组与字符串的补充,挑选的是那本LeetBook没有的题目。
1.删除排序数组中的重复项 II
public int removeDuplicates(int[] nums) {
if (nums == null) return 0;
if (nums.length <= 2) return nums.length;
int j = 2;
for (int i = 2; i < nums.length; i++) {
if (nums[i] != nums[j - 2]) {
nums[j++] = nums[i];
}
}
return j;
}
2.验证回文串
public boolean isPalindrome(String s) {
s = s.replaceAll("[^0-9A-Za-z]", "").toLowerCase();
return s .equals(new StringBuffer(s).reverse().toString());
}
3.反转字符串中的元音字母
//345. 反转字符串中的元音字母
public String reverseVowels(String s) {
HashSet<Character> set = new HashSet<>(//无序集合更好
Arrays.asList('a', 'e', 'i', 'o', 'u', 'A', 'E', 'I', 'O', 'U'));
char[] result = new char[s.length()];//不能在原来的字符串改,只能新建一个作为结果
int i = 0, j = s.length() - 1;//双指针(对撞指针)
while (i <= j) {//一定要包含等于
char chari = s.charAt(i);//注意这里先用两个变量保存好
char charj = s.charAt(j);//因为等号左边的i可是会影响右边的哦
if (!set.contains(s.charAt(i))) {
// result[i++] = s.charAt(i);
result[i++] = chari;
} else if (!set.contains(s.charAt(j))) {
// result[j--] = s.charAt(j);
result[j--] = charj;
} else {// 反转在这里完成
result[i++] = charj;
result[j--] = chari;
}
}
return String.valueOf(result);//不能用result.toString()
}
4.盛最多水的容器
//11. 盛最多水的容器
public int maxArea(int[] height) {
// int i = 0, j = height.length - 1, maxInt = Integer.MIN_VALUE;
// while (i < j) {
// maxInt = Math.max(maxInt, (j - i) * Math.min(height[i], height[j]));
// }
/* int maxInt = Integer.MIN_VALUE;
for (int i = 0; i < height.length - 1; i++) {
for (int j = i + 1; j < height.length; j++) {
maxInt = Math.max(maxInt, (j - i) * Math.min(height[i], height[j]));
}
}
return maxInt;*/
// 设计对撞指针,重点在于设计两指针的移动策略,这个需要观察题目要求及规律
// 可以观察到,这个有点像木桶效应,题目也在暗示这个方向
// 即由高度小的一边来决定容量的大小,我们在while循环里更新 maxarea,并将指向较短线段的指针向较长线段那端移动1
int i = 0, j = height.length - 1, res = 0;
while (i < j) {
res = height[i] < height[j] ? Math.max(res, (j - i) * height[i++]) : Math.max(res, (j - i) * height[j--]);
}
return res;
}
5.三数之和
三重循环超时
排序后用对撞双指针
public List<List<Integer>> threeSum(int[] nums) {
// List<Integer> list = new ArrayList<>();
List<List<Integer>> res = new ArrayList<>();
Arrays.sort(nums);
// for (int i = 0; i < nums.length - 2; i++) {
// if (nums[i] > 0 || (i > 0 && nums[i] == nums[i - 1]))
// continue;
// for (int j = i + 1; j < nums.length - 1; j++) {
// if (j > i + 1 && nums[j] == nums[j - 1])
// continue;
// for (int k = j + 1; k < nums.length; k++) {
// if (k > j + 1 && nums[k] == nums[k - 1])
// continue;
// int sum = nums[i] + nums[j] + nums[k];
// if (sum == 0) {
// // list.addAll(Arrays.asList(nums[i], nums[j], nums[k]));
// List<Integer> list = new ArrayList<>(Arrays.asList(nums[i], nums[j], nums[k]));
// res.add(list);
// }
// }
// }
// }
for (int i = 0; i < nums.length - 2; i++) {
if (nums[i] > 0 || (i > 0 && nums[i] == nums[i - 1])) {
continue;
}
int j = i + 1, k = nums.length - 1;
while (j < k) {
int sum = nums[i] + nums[j] + nums[k];
if (sum < 0) {
while (j < k && nums[j] == nums[++j]);
} else if (sum > 0) {
while (j < k && nums[k] == nums[--k]);
} else {
res.add(new ArrayList<>(Arrays.asList(nums[i], nums[j], nums[k])));
while (j < k && nums[j] == nums[++j]);
while (j < k && nums[k] == nums[--k]);
}
}
}
return res;
}
6.最大子序和
public int maxSubArray(int[] nums) {
if (nums.length == 0) {
return 0;
}
int maxSum = nums[0];
for (int i = 1; i < nums.length; i++) {
if(nums[i - 1] > 0) {
nums[i] += nums[i - 1];
}
maxSum = Math.max(maxSum, nums[i]);
}
return maxSum;
// 贪心算法
// int maxSum = nums[0], sum = nums[0];
// for (int i = 1; i < nums.length; i++) {
// sum = Math.max(sum + nums[i], nums[i]);
// maxSum = Math.max(maxSum, sum);
// }
// return maxSum;
// 暴力法
// if (nums == null || nums.length == 0) {
// return 0;
// }
// int maxSum = Integer.MIN_VALUE;
// for (int i = 0; i < nums.length; i++) {
// int sum = 0;
// for (int j = i; j < nums.length; j++) {
// sum += nums[j];
// maxSum = Math.max(maxSum, sum);
// }
// }
// return maxSum;
}
7.数组中的第K个最大元素
// public int findKthLargest(int[] nums, int k) {
// PriorityQueue<Integer> pq = new PriorityQueue<>();
// for (int i = 0; i < nums.length; i++) {
// pq.offer(nums[i]);
// if (i >= k) {
// pq.poll();
// }
// }
// return pq.peek();
// }
public int findKthLargest(int[] nums, int k) {
k = nums.length - k;
int l = 0, h = nums.length - 1;
while (l < h) {
int p = partition(nums, l, h);
if (p == k) {
break;
} else if (p < k) {
l = p + 1;
} else {
h = p - 1;
}
}
return nums[k];
}
private int partition(int[] nums, int low, int high) {
int key = nums[low];
int i = low, j = high + 1;
while (true) {
while (nums[--j] > key && j > low);
while (nums[++i] < key && i < high);
if (i >= j) {
break;
}
swap(nums, i, j);
}
swap(nums, low, j);
return j;
}
private void swap(int[] nums, int i, int j) {
int tmp = nums[i];
nums[i] = nums[j];
nums[j] = tmp;
}