leet code 每日三道题 01 array+binary search
29题 除法 M 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 package com.leetcode;import java.util.Arrays;public class DivideTwoIntegers { public static void main (String[] args) { System.out.println(solution.divideTwo(Integer.MIN_VALUE, Integer.MAX_VALUE)); } public static class solution { public static int divide (int dividend, int divisor) { if (dividend == Integer.MIN_VALUE && divisor == 1 ) return dividend; if (dividend == Integer.MIN_VALUE && divisor == -1 ) return Integer.MAX_VALUE; boolean isPos = (dividend > 0 && divisor > 0 ) || (dividend < 0 && divisor < 0 ); long array[] = new long [32 ]; long result = 0 ; divisor = Math.abs(divisor); long dividentInput = dividend; dividentInput = Math.abs(dividentInput); array[0 ] = divisor; int truePosi = 0 ; for (int i = 1 ; i < array.length; i++) { array[i] = array[i - 1 ] << 1 ; if (array[i] < 0 ) { break ; } truePosi = i; } for (int i = truePosi; i >= 0 ; i--) { if (array[i] <= dividentInput) { result += 1 << i; dividentInput -= array[i]; } } if (result > Integer.MAX_VALUE) result = Integer.MAX_VALUE; if (result < Integer.MIN_VALUE) result = Integer.MIN_VALUE; if (isPos) return (int ) result; else return (int ) -result; } public static int divideTwo (int dividend, int divisor) { if (dividend == divisor) return 1 ; if (dividend == Integer.MIN_VALUE && divisor == 1 ) return dividend; if (dividend == Integer.MIN_VALUE && divisor == Integer.MAX_VALUE) return -1 ; if (divisor == Integer.MAX_VALUE && divisor == -dividend) return -1 ; if (divisor == Integer.MAX_VALUE || divisor == Integer.MIN_VALUE) return 0 ; int result = 0 ; long [] array = new long [32 ]; boolean isPos = (dividend > 0 && divisor > 0 ) || (dividend < 0 && divisor < 0 ); if (divisor < 0 ) divisor = -divisor; array[0 ] = divisor; for (int i = 1 ; i < array.length; i++) { array[i] = array[i - 1 ] << 1 ; } if (dividend == Integer.MIN_VALUE) { for (int i = array.length - 1 ; i >= 0 ; i--) { if (dividend <= -array[i]) { dividend += array[i]; result += 1 << i; if (result<0 ) return Integer.MAX_VALUE; } } } else { if (dividend < 0 ) dividend = -dividend; for (int i = array.length - 1 ; i >= 0 ; i--) { if (dividend >= array[i]) { dividend -= array[i]; result += 1 << i; } } } if (isPos) return result; else return -result; } } }
问题:不使用 * / % 符号完成除法
思路:1. 暴力算法,除法可以看作减法,每次减去被除数,当结果<0说明结束,但是这样会导致被除数为1的时候循环次数为被除数,会超时的
思路:2. 首先位运算 除2:>>1
乘2:<<1
。然后我们看整个除法表达式,比如 13/4 = 3 ==> 13 = 4 * 3
换算成二进制:1101 = 4 * 0010+ 4* 0001
也就是4个 0010
和0001
,所以可以看出规律,那就是除法的结果必定为除数的倍数的二进制位。
由此可以遍历二进制数(从 1000.. 遍历到 000..001),题目的最大是32位,现在假如最高8位,那么从最高位开始 1000 0000 * 4 > 1010
循环直到发现0010(2) * 4 < 1101
,记录下0010
, 那么剩下是数就是 13-8=5 ,继续遍历0001 * 4 < 5
记录下0001
,遍历结束,结果为 0001 *4 + 0010 * 4
即 0001 + 0010
(3) * 4 ,最后结果为 3。
具体实现中,为了不使用乘法符号完成乘法,使用<<
比如 0001
和0010
分别乘4就是 4 和 4<<1,所以可以定义一个初始数组arr,arr[0]
放被除数,1,2,3 分别是前一位的乘2即<<1。
33 Search in Rotated Sorted Array M 这题应该挺简单的,不停二分就是了,既然100%了就不看官方答案了
* 题目是给定一个未知的数,数组会根据这个数旋转,
* For example, [0,1,2,4,5,6,7] might be rotated at pivot index 3 and become [4,5,6,7,0,1,2].
*
* 思路:二分法,反正第一个数肯定是比最后一位大,数组二分,筛选出目标数组,第一个数比分组后的最后一个大就是目标数组,
* 将目标数组再次二分,这个数再比对两个数组的最后一个数,找出最小的所在的数组,直到目标数组为1 记录下标,
*
* 找到记录下标后说明确定了分割位置,将数组分割成两个有序数组,然后二分查找即可
代码逻辑
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 package com.leetcode;import java.util.Arrays;public class SearchInRotatedSortedArray33 { public static void main (String[] args) { System.out.println(new Solution().search(new int []{ 1 ,3 ,5 }, 1 )); } static class Solution { public int search (int [] nums, int target) { int posi = doSplitArray(nums, nums[0 ], 0 , nums.length - 1 ); int res = doBinarySearch(nums, 0 , posi - 1 , target); if (res != -1 ) return res; else return doBinarySearch(nums, posi, nums.length - 1 , target); } private int doSplitArray (int [] nums, int n, int start, int end) { if (start > end) return 0 ; if (start == end) return start; int mid = (start + end) / 2 ; if (n <= nums[start] && n < nums[end]) return 0 ; else if (n > nums[start] && n > nums[end]) return start; else if (n <= nums[start] && n > nums[end]) { if (n <= nums[mid]) return doSplitArray(nums, n, mid + 1 , end); else return doSplitArray(nums, n, start, mid); } else return -1 ; } private int doBinarySearch (int [] nums, int start, int end, int target) { if (start > end || (start == end && nums[start] != target)) return -1 ; int mid = (start + end) / 2 ; if (nums[mid] == target) return mid; else if (nums[mid] > target) return doBinarySearch(nums, start, mid, target); else return doBinarySearch(nums, mid + 1 , end, target); } } }
34. Find First and Last Position of Element in Sorted Array M 二分就行的题目 , 30分钟 100%+95%
题目
给定一个排序数组,找出目标的起始位置和终点位置下标
思路:先定位到目标,然后从目标往前和往后看是否连续,记录最后一次连续下标
Given an array of integers nums sorted in ascending order, find the starting and ending position of a given target value.
If target is not found in the array, return [-1, -1].
Follow up: Could you write an algorithm with O(log n) runtime complexity?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 class Solution { public int [] searchRange(int [] nums, int target) { if (nums.length == 0 ) return new int []{-1 , -1 }; int res = binarySearch(nums, 0 , nums.length - 1 , target); if (res == -1 ) return new int []{-1 , -1 }; int s = res, e = res; while (s > 0 && nums[s] == nums[s - 1 ]) s--; while (e < nums.length - 1 && nums[e] == nums[e + 1 ]) e++; return new int []{s, e}; } private int binarySearch (int [] nums, int start, int end, int target) { if (start > end || (start == end && nums[start] != target)) return -1 ; int mid = (start + end) / 2 ; if (nums[mid] == target) return mid; else if (nums[mid] > target) return binarySearch(nums, start, mid, target); else return binarySearch(nums, mid + 1 , end, target); } }
35. Search Insert Position easy easy 题 没什么好说的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 package com.leetcode;public class SearchInsertPosition35 { public static void main (String[] args) { System.out.println(new Solution().searchInsert(new int []{1 , 3 , 5 , 6 }, 5 )); } static class Solution { public int searchInsert (int [] nums, int target) { return doBinarySearch(nums, 0 , nums.length - 1 , target); } public int doBinarySearch (int [] nums, int start, int end, int target) { if (start > end) return -1 ; if (start == end) { if (target <= nums[start]) return start; else return start + 1 ; } int mid = (start + end) / 2 ; if (nums[mid]==target) return mid; else if (nums[mid] > target) return doBinarySearch(nums, start, mid, target); else return doBinarySearch(nums, mid + 1 , end, target); } } }