1. 704.二分查找(2024.6.16)
public class Solution {
public static int search(int[] nums, int target) {
int left = 0;
int right = nums.length - 1;
// 避免当 target 小于nums[0] nums[nums.length - 1]时多次循环运算
if (nums.length == 0 || target < nums[0] || target > nums[right]) {
return -1;
}
while (left <= right) {
//下面这一行不能放while外面,每次循环要更新逮嘛!!!
int mid = left + ((right - left) >> 1);
if (nums[mid] < target)
left = mid + 1;
else if (nums[mid] > target)
right = mid - 1;
else return mid;
}
return -1;
}
}
2. 35.搜索插入位置(2024.6.17)
class Solution {
public int searchInsert(int[] nums, int target) {
//无重复元素 的 升序 排列数组,该想到二分法
int left = 0;
int right = nums.length - 1;
while(left <= right) {
int mid = left + ((right - left)>> 1);
if(target > nums[mid]) {
left = mid + 1;
}
else if(target < nums[mid]) {
right = mid - 1;
}
else return mid;
}
//精髓
return right + 1;
}
}
3. 34.在排序数组中查找元素的第一个和最后一个位置(2024.6.17)
class Solution {
public int[] searchRange(int[] nums, int target) {
int index = binarySearch(nums, target);
if(index == -1) {
return new int[]{-1, -1};
}
int left = index;
int right = index;
// 判断数组越界的条件必须放前面,不然可能引起空指针异常
// left-- >= 0 && nums[left--] == nums[index] 中,使用了递减运算符 -- 在 left 变量上,但这种用法是不正确的,因为递减运算符不能在逻辑表达式中连续使用。
// 向左滑动,找左边界
while (left - 1 >= 0 && nums[left - 1] == target) { // 防止数组越界。逻辑短路,两个条件顺序不能换
left--;
}
// 向右滑动,找右边界
while (right + 1 < nums.length && nums[right + 1] == target) { // 防止数组越界。
right++;
}
return new int[] {left, right};
}
public int binarySearch(int[] nums, int target) {
int left = 0;
int right = nums.length - 1;
if(nums.length == 0 || target < nums[0] || target >nums[right]) {
return -1;
}
while(left <= right) {
int mid = left + ((right - left)>>1);
if(target < nums[mid]) {
right = mid - 1;
}
else if(target > nums[mid]) {
left = mid + 1;
}
else return mid;
}
return -1;
}
}
4. 69.x 的平方根 (2024.6.18)
class Solution {
public int mySqrt(int x) {
long left = 0;
long right = x ;
while (left <= right) {
long mid =left + ((right - left)>> 1);
long square = mid * mid;
if (square == x) {
return (int) mid;
}
else if (square < x) {
left = mid + 1;
}
else if(square > x) {
right = mid - 1;
}
}
return (int) right;
}
}
5. 367.有效的完全平方数 (2024.6.18)
class Solution {
public boolean isPerfectSquare(int num) {
int left = 0;
// num/2和num == 0 || num == 1这两步可以让性能提升
int right =num/2;
if (num == 0 || num == 1) {
return true;
}
while (left <= right) {
int mid = left + ((right - left)>>1);
// 注意这个平方要用long修饰,一个int平方后很大
long square = (long) mid * mid;
if (square < num) {
left = mid + 1;
}
else if(square > num){
right = mid - 1;
}
else return true;
}
return false;
}
}
6. 27.移除元素(2024.6.18)
class Solution {
public int removeElement(int[] nums, int val) {
//双指针的初次接触
int fast, slow = 0;
for(fast = 0; fast < nums.length; fast++) {
if(nums[fast] != val) {
nums[slow] = nums[fast];
slow++;
}
}
return slow;
}
}
7. 283.移动零(2024.6.19)
class Solution {
public void moveZeroes(int[] nums) {
if(nums.length < 2) {
return;
}
int fast = 0, slow = 0;
while(fast < nums.length) {
if(nums[fast] != 0) {
nums[slow] = nums[fast];
slow++;
}
fast++;
}
for(int i = slow; i < nums.length; i++) {
nums[i] = 0;
}
}
}
8. 26.删除有序数组中的重复项(2024.6.20)
class Solution {
public int removeDuplicates(int[] nums) {
if(nums.length < 2) {
return nums.length;
}
int fast , slow = 0;
for(fast = 1; fast < nums.length; fast++) {
if(nums[fast] != nums[slow]) {
slow++;
nums[slow] = nums[fast];
}
}
return slow + 1;
}
}
9. 844.比较含退格的字符串(2024.6.20)
class Solution {
public boolean backspaceCompare(String s, String t) {
return build(s).equals(build(t));
}
public String build(String str) {
StringBuffer sb = new StringBuffer();
for(int i = 0; i <str.length(); i++) {
char ch = str.charAt(i);
if(ch != '#') {
sb.append(ch);
}
else {
if(sb.length() > 0) {
sb.deleteCharAt(sb.length() - 1);
}
}
}
return sb.toString();
}
}
10 . 977.有序数组的平方 (2024.6.20)
class Solution {
public int[] twoSum(int[] numbers, int target) {
// 双指针收缩
int left = 0;
int right = numbers.length - 1;
while (left < right) {
int sum = numbers[left] + numbers[right];
if(sum == target) {
return new int[] {left + 1, right + 1};
} else if(sum > target) {
right--;
} else {
left++;
}
}
return new int[0];
}
}
11 . 209.长度最小的子数组(2024.6.21)
class Solution {
public int minSubArrayLen(int target, int[] nums) {
int fast, slow = 0;
int result = Integer.MAX_VALUE;
int sum = 0;
for(fast = 0; fast < nums.length; fast++) {
sum += nums[fast];
while(sum >= target) {
result = Math.min(result, fast - slow + 1);
sum -= nums[slow];
slow++;
}
}
return result== Integer.MAX_VALUE ? 0 : result;
}
}
12. 167.两数之和 II - 输入有序数组(2024.6.22)
class Solution {
public int[] twoSum(int[] numbers, int target) {
// 双指针收缩
int left = 0;
int right = numbers.length - 1;
while (left < right) {
int sum = numbers[left] + numbers[right];
if(sum == target) {
return new int[] {left + 1, right + 1};
} else if(sum > target) {
right--;
} else {
left++;
}
}
return new int[0];
}
}
13. 15.三数之和(2024.6.23)
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
Arrays.sort(nums);
List<List<Integer>> answer = new ArrayList<>();
//先拿一个第一个做枚举
for(int k = 0; k < nums.length - 2; k++){
//先对两种特殊情况做优化
if((nums[k] + nums[k + 1] + nums[k + 2]) > 0) return answer;
if((nums[k] + nums[nums.length - 1] + nums[nums.length - 2]) < 0) continue;
//不重复
if(k > 0 && nums[k] == nums[k - 1]) continue;
//双指针收缩
int left = k + 1;
int right = nums.length - 1;
while(left < right){
int sum = nums[k] + nums[left] + nums[right];
if(sum < 0){
left ++;
//这里的left <right 条件必须加上,因为是循环,反复减很有可能减到边界之外
while (left <right && nums[left] == nums[left - 1]) {
left ++;
}
// while(left < right && nums[left] == nums[++left]);
} else if (sum > 0) {
right --;
while (left <right && nums[right] == nums[right + 1]) {
right --;
}
// while(left < right && nums[right] == nums[--right]);
} else {
List<Integer> list = new ArrayList<Integer> ();
list.add(nums[k]);
list.add(nums[left]);
list.add(nums[right]);
answer.add(list);
// answer.add(new ArrayList<Integer>(Arrays.asList(nums[k], nums[left], nums[right])));
left ++;
while (left <right && nums[left] == nums[left - 1]) {
left ++;
}
right --;
while (left <right && nums[right] == nums[right + 1]) {
right --;
}
// while(left <right && nums[left] == nums[++left]);
// while(left <right && nums[right] == nums[--right]);
}
}
}
return answer;
}
}
14. 11. 盛最多水的容器 (2024.6.24)
class Solution {
public int maxArea(int[] height) {
int left = 0;
int right = height.length - 1;
int answer = 0;
while (left < right) {
int area = (right - left) * Math.min(height[left], height[right]);
answer = Math.max(area, answer);
if (height[left] > height[right]) {
right--;
} else {
left++;
}
}
return answer;
}
}
15. 42. 接雨水 (2024.6.25)
class Solution {
public int trap(int[] height) {
if (height.length == 0) {
return 0;
}
int n = height.length;
int res = 0;
// 数组充当备忘录
int[] l_max = new int[n];
int[] r_max = new int[n];
// 初始化 base case
l_max[0] = height[0];
r_max[n - 1] = height[n - 1];
// 从左向右计算 l_max
for (int i = 1; i < n; i++)
l_max[i] = Math.max(height[i], l_max[i - 1]);
// 从右向左计算 r_max
for (int i = n - 2; i >= 0; i--)
r_max[i] = Math.max(height[i], r_max[i + 1]);
// 计算答案
for (int i = 1; i < n - 1; i++)
res += Math.min(l_max[i], r_max[i]) - height[i];
return res;
}
}