算法-数组|704.二分查找、35.搜索插入的位置 34. 在排
一、 LeetCode 704 二分查找
题目连接: https://leetcode.cn/problems/binary-search/
思路:使用两个变量定义左右边界,如[left, right] 使tartget和mid的位置的比较,比mid位置的值大,则说明target在右区间,既修改left = mid + 1; 如果target比mid位置的值小,则说明target在左区间,既修改right = mid - 1;如果相等则返回mid的索引。都没找到则返回-1;
定义[left, right]区间查找
class Solution {
public int search(int[] nums, int target) {
if (nums == null || nums.length == 0) return -1;
int left = 0;
int right = nums.length - 1;
while (left <= right) {
int mid = left + (right - left) / 2;
if (target > nums[mid]) {
left = mid + 1;
} else if (target < nums[mid]) {
right = mid - 1;
} else {
return mid;
}
}
return -1;
}
}
使用[left, right)
class Solution {
public int search(int[] nums, int target) {
if (nums == null || nums.length == 0) return -1;
if (target < nums[0] || target > nums[nums.length - 1]) return -1;
int left = 0;
int right = nums.length;
while (left < right) {
int mid = left + (right - left) / 2;
if (target > nums[mid]) {
left = mid + 1;
} else if (target < nums[mid]) {
right = mid;
} else {
return mid;
}
}
return -1;
}
}
二、 LeetCode 35 搜索插入的位置
题目连接: https://leetcode.cn/problems/search-insert-position/
思路:使用二分查找[left, right),找到了既mid位置的值,没有找到则返回right的位置索引
class Solution {
public int searchInsert(int[] nums, int target) {
if (target < nums[0]) return 0;
if (target > nums[nums.length - 1]) return nums.length;
int left = 0;
int right = nums.length;
while (left < right) {
int mid = left + (right - left) / 2;
if (target > nums[mid]) {
left = mid + 1;
} else if (target < nums[mid]) {
right = mid;
} else {
return mid;
}
}
return right;
}
}
三、LeetCode 34 在排序数组中查找元素的第一个和最后一个位置
题目连接:https://leetcode.cn/problems/find-first-and-last-position-of-element-in-sorted-array/
思路:使用二分查找法找到target的索引,如果为找到返回[-1, -1],如果找到了index,在分别向左边循环查找左边界,向右边循环查找右边界
class Solution {
private int binarySearch(int[] nums, int target){
int left = 0;
int right = nums.length - 1;
while (left <= right) {
int mid = left + (right - left) / 2;
if (nums[mid] > target) {
right = mid - 1;
} else if (nums[mid] < target) {
left = mid + 1;
} else {
return mid;
}
}
return -1;
}
public int[] searchRange(int[] nums, int target) {
if (nums == null || nums.length == 0) return new int[]{-1, -1};
if (target < nums[0] || target > nums[nums.length - 1]) return new int[]{-1, -1};
int index = binarySearch(nums, target);
if (index == -1) return new int[]{-1, -1};
int left = index;
int right = index;
while (left - 1 >= 0 && (nums[left - 1] == nums[index])) {
left--;
}
while (right + 1 <= nums.length - 1 && (nums[right + 1] == nums[index])) {
right++;
}
return new int[]{left, right};
}
}
四、 69. x 的平方根
题目连接:https://leetcode.cn/problems/sqrtx
思路:使用二分查找法分别尝试[0, x /2] ,相等的mid返回,不相等的最后取出right值返回
class Solution {
public int mySqrt(int x) {
if (x == 0 || x == 1) return x;
int left = 1;
int right = x / 2;
while (left <= right) {
int mid = left + (right - left) / 2;
if (mid > x / mid) {
right = mid - 1;
} else if (mid < x / mid) {
left = mid + 1;
} else {
return mid;
}
}
return right;
}
}
五、 367. 有效的完全平方数
题目连接:https://leetcode.cn/problems/valid-perfect-square/
思路:使用二分查找法,如果num / mid == mid并且没有余数则返回true
class Solution {
public boolean isPerfectSquare(int num) {
if (num == 0 || num == 1) return true;
int left = 1;
int right = num / 2;
while (left <= right) {
int mid = left + (right - left) / 2;
if (mid > num / mid) {
right = mid - 1;
} else if (mid < num / mid) {
left = mid + 1;
} else {
if (num % mid == 0) {
return true;
} else {
return false;
}
}
}
return false;
}
}
另一种写法:使用mid * mid == num判断,注意left, right ,mid, temp可能会超过int的最大值 因此使用long定义变量
class Solution {
public boolean isPerfectSquare(int num) {
long left = 0;
long right = num;
while (left <= right) {
long mid = left + (right - left) / 2;
long temp = mid * mid;
if (temp > num) {
right = mid - 1;
} else if (temp < num) {
left = mid + 1;
} else {
return true;
}
}
return false;
}
}
六、 27. 移除元素
题目连接:https://leetcode.cn/problems/remove-element/
思路:定义快慢指针,在快指针里搜索非val的值更新到slow指针的数组里面
class Solution {
public int removeElement(int[] nums, int val) {
if (nums == null || nums.length == 0) return 0;
int slowIndex = 0;
for (int fastIndex = 0; fastIndex < nums.length; fastIndex++) {
if (nums[fastIndex] != val) {
nums[slowIndex++] = nums[fastIndex];
}
}
return slowIndex;
}
}
七、26. 删除有序数组中的重复项
题目连接:https://leetcode.cn/problems/remove-duplicates-from-sorted-array/
思路:使用快慢指针,快指针和慢指针指的内容不相等,即和以前的元素不一样的时候,slow++ 在更新slow内容
class Solution {
public int removeDuplicates(int[] nums) {
int slowIndex = 0;
for (int fastIndex = 1; fastIndex < nums.length; fastIndex++) {
if (nums[slowIndex] != nums[fastIndex]) {
nums[++slowIndex] = nums[fastIndex];
}
}
return slowIndex + 1;
}
}
八、283. 移动零
题目连接:https://leetcode.cn/problems/move-zeroes/
思路:使用快慢指针,使得非0的数字移动到左边,剩下的slowIndex后面的都重置成0
class Solution {
public void moveZeroes(int[] nums) {
if (nums == null || nums.length == 0) return;
int slowIndex = 0;
for (int fastIndex = 0; fastIndex < nums.length; fastIndex++){
if (nums[fastIndex] != 0) {
nums[slowIndex++] = nums[fastIndex];
}
}
for (int i = slowIndex; i < nums.length; i++) {
nums[i] = 0;
}
}
}
九、844. 比较含退格的字符串
题目连接:https://leetcode.cn/problems/backspace-string-compare/
思路:1、使用栈结构特性,遇到'#'弹出最后一个元素(注意判断栈是否为空),遇到非'#'就入栈,最后一次弹出栈得到的字符串做比较,这里可以使用StringBuilder模拟入栈(append)出栈(deleteCharAt)操作
2、使用双指针,从字符串的后面向前遍历,遇到'#'计数+1,不是'#'计数-1,直到计数等于0停止下来,比较两个位置的字符是否相等,不相等则返回false,相等i-- j--继续比较,如果遍历结束了既i < 0 || j < 0 则退出while(true) 判断两个是否到遍历完了,都遍历完了则返回true
1、使用栈的方式
class Solution {
private String getString(String s) {
if (s == null ||s.length() == 0) return s;
StringBuilder stringBuilder = new StringBuilder();
for (int i = 0; i < s.length(); i++){
char c = s.charAt(i);
if (c == '#') {
if (stringBuilder.length() != 0) {
stringBuilder.deleteCharAt(stringBuilder.length() - 1);
}
} else {
stringBuilder.append(c);
}
}
return stringBuilder.toString();
}
public boolean backspaceCompare(String s, String t) {
return getString(s).equals(getString(t));
}
}
2、使用双指针
class Solution {
public boolean backspaceCompare(String s, String t) {
int i = s.length() - 1;
int j = t.length() - 1;
int sNumber = 0;
int tNumber = 0;
while (true) {
while (i >= 0) {
if (s.charAt(i) == '#') sNumber++;
else {
if (sNumber > 0) sNumber--;
else break;
}
i--;
}
while (j >= 0) {
if (t.charAt(j) == '#') tNumber++;
else {
if (tNumber > 0) tNumber--;
else break;
}
j--;
}
if (i < 0 || j < 0) break;
if (s.charAt(i) != t.charAt(j)) return false;
i--;
j--;
}
return i == -1 && j == -1;
}
}
十、977. 有序数组的平方
题目连接:https://leetcode.cn/problems/squares-of-a-sorted-array/
思路:使用首尾指针,取平方最大的值放在结果集的最右边
class Solution {
public int[] sortedSquares(int[] nums) {
int left = 0;
int right = nums.length - 1;
int[] result = new int[nums.length];
int j = result.length - 1;
while (left <= right) {
int leftValue = nums[left] * nums[left];
int rightValue = nums[right] * nums[right];
if (leftValue > rightValue) {
result[j--] = leftValue;
left++;
} else {
result[j--] = rightValue;
right--;
}
}
return result;
}
}