当前位置:网站首页>Leetcode dichotomy

Leetcode dichotomy

2022-06-22 13:21:00 Linchong Fengxue mountain temple

leetcode- Dichotomy _MaYingColdPlay The blog of -CSDN Blog 33. Search rotation sort array https://blog.csdn.net/MaYingColdPlay/article/details/105616101?spm=1001.2014.3001.5502

Two points search _MaYingColdPlay The blog of -CSDN Blog 4. Find the median of two positive arrays https://blog.csdn.net/MaYingColdPlay/article/details/108743359?spm=1001.2014.3001.5502

There are two kinds of dichotomy , One is that there is left,right, then mid Equal to the sum of the two and divide by 2, Binary search . The other one is to search in half during recursion .

Two points ,left = mid -1;right = mid + 1 , It is mainly to find the conditions for pointer movement (check function ), Write according to the meaning of the title check function , For example, cocoa, which likes bananas , Want to find h  Minimum speed to eat all bananas in hours  k,check On the condition that , When nums[mid]>=target, Speed can be reduced .

leetcode- Fast power / square / Add up / be divided by _MaYingColdPlay The blog of -CSDN Blog 69. x The square root of https://leetcode-cn.com/problems/sqrtx/https://blog.csdn.net/MaYingColdPlay/article/details/119718239?spm=1001.2014.3001.5501

4. seek 2 The median of a positive array

34. Find the first and last positions of the elements in the sort array

  Two ways to write a separate interval

Power button

Left boundary : shrinkage r, another r=mid, Use template 1

  Right border : shrinkage l, another l=mid, Use template 2

Finally back to r And return l It's the same , Because the cyclic condition is while l<r, At the end of the exit, the two are equal .

class Solution {
    public int[] searchRange(int[] nums, int target) {
        if(nums.length == 0) return new int[]{-1,-1};
    
        int l = 0, r = nums.length - 1; // Dichotomous range 
        while( l < r)			        // Find the starting position of the element 
        {
            int mid = (l + r )/2;
            if(nums[mid] >= target) r = mid;
            else l = mid + 1;
        }
        if( nums[r] != target) return new int[]{-1,-1}; // To find the failure 
        int L = r;
        l = 0; r = nums.length - 1;     // Dichotomous range 
        while( l < r)			        // Find the end position of the element 
        {
            int mid = (l + r + 1)/2;
            if(nums[mid] <= target ) l = mid;
            else r = mid - 1;
        }
        return new int[]{L,r};
    }
}

 author :lin-shen-shi-jian-lu-k
 link :https://leetcode-cn.com/problems/find-first-and-last-position-of-element-in-sorted-array/solution/tu-jie-er-fen-zui-qing-xi-yi-dong-de-jia-ddvc/
 source : Power button (LeetCode)
 The copyright belongs to the author . Commercial reprint please contact the author for authorization , Non-commercial reprint please indicate the source .
# Find the leftmost subscript , And the rightmost subscript ,2 The second dichotomy 
# The leftmost subscript , When check be equal to target When , Shrink the right border , Therefore, it can be judged that the condition is nums[mid]>=target
# The rightmost subscript , When check be equal to target When , Shrink the left border , Therefore, it can be judged that the condition is nums[mid]<=target
class Solution:
    def searchRange(self, nums, target):
        left=0
        right=len(nums)-1
        # Find the left border 
        while left<right:
            mid=(left+right)//2
            if nums[mid]>=target:
                right=mid
            else:
                left=mid+1
        if nums[right] != target:
            return [-1, -1]
        a1=right


        left = 0
        right = len(nums) - 1
        #  Find the right border 
        while left < right:
            mid = (left + right+1) // 2
            if nums[mid] <= target:
                left = mid
            else:
                right = mid-1
        a2=left
        return [a1,a2]
# nums = [5,7,7,8,8,10]
# target = 8
nums = [5,7,7,8,8,10]
target=6
res=Solution().searchRange(nums,target)
print(res)

Use the way of adding and subtracting one to everything

When looking for the left boundary , The judgment condition is

nums[mid] >= target, If nums[mid] Greater than or equal to target, Just move the pointer to the left , Because on the left side, there are still those who meet the conditions , The left border hasn't arrived yet .

Decide which boundary to change according to the judgment conditions .

the last one nums[mid] >= target Of mid It's the left boundary .

class Solution(object):
    def searchRange(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: List[int]
        """
        if not nums:
            return [-1,-1]
        # Find the left border 
        left = 0
        right = len(nums) - 1
        while left <= right:
            mid = (left + right) // 2
            if nums[mid] >= target:
                right = mid - 1
            else:
                left = mid + 1
        if right+1 < len(nums) and nums[right+1] == target:
            b1 = right + 1
        else:
            b1 = -1

        # Find the right border 
        left = 0
        right = len(nums) - 1
        while left <= right:
            mid = (left + right) // 2
            if nums[mid] <= target:
                left = mid + 1
            else:
                right = mid - 1
        if left - 1 >=0 and nums[left-1] == target:
            b2 = left - 1
        else:
            b2 = -1
        return [b1,b2]

2064. The minimum value of the most items allocated to the store

 

  Dichotomous sub problem

class Solution {
public:
    bool check(vector<int> &quantities,int n,int x){
        if(x == 0)return false;
        int m = quantities.size(),counts = 0;
        for(int i = 0; i < m;++i){
            counts += ceil((double)quantities[i] / x);
        }
        return counts <= n;
    }
    int minimizedMaximum(int n, vector<int>& quantities) {
        int left = 0,right = 100000;
        while(left < right){
            int mid = (right-left)/2 + left;
            if(check(quantities,n,mid)){
                right = mid;
            }else
                left = mid+1; 
        }
        return left;
    }
};

 author :liyinxin
 link :https://leetcode-cn.com/problems/minimized-maximum-of-products-distributed-to-any-store/solution/c-er-fen-cha-zhao-by-liyinxin-l4f3/
 source : Power button (LeetCode)
 The copyright belongs to the author . Commercial reprint please contact the author for authorization , Non-commercial reprint please indicate the source .

/**
 * @param {number} n
 * @param {number[]} quantities
 * @return {number}
 */
var minimizedMaximum = function(n, quantities) {
    let right = Math.max(...quantities);
    let left = 1;

    while(left <= right) {
        let mid = (left + right) >> 1;
        if(checked(mid)) {
            right = mid - 1;
        } else {
            left = mid + 1;
        }
    }

    function checked(num) {
        let ans = 0;

        for(let i=0; i<quantities.length; i++) {
            ans += Math.ceil(quantities[i] / num);
        }

        return ans <= n;
    }

    return left;

};

 author :getify
 link :https://leetcode-cn.com/problems/minimized-maximum-of-products-distributed-to-any-store/solution/javascript-zui-da-zhi-zui-xiao-hua-wen-t-rr2v/
 source : Power button (LeetCode)
 The copyright belongs to the author . Commercial reprint please contact the author for authorization , Non-commercial reprint please indicate the source .
class Solution(object):
    def minimizedMaximum(self, n, quantities):
        """
        :type n: int
        :type quantities: List[int]
        :rtype: int
        """
        # Set the maximum number of items allocated to the store as x
        # Greedy thoughts :quantities[i]/x  Must be less than or equal to n.
        # Find this threshold . Just enough quantities[i]/x  Must be less than or equal to n
        def check(x):
            total_cnt = 0
            for q in quantities:
                cnt = q // x
                if q % x != 0:
                    cnt +=1
                total_cnt += cnt
            if total_cnt > n:
                return False
            else:
                return True
        left=0
        right=100000
        while left<right:
            mid=(left+right)//2
            if mid==0:
                return 1
            if check(mid):
                right=mid 
            else:
                left=mid+1
        return left
            
        

875. Coco, who loves bananas

  Dichotomous sub problem

class Solution(object):
    def minEatingSpeed(self, piles, h):
        """
        :type piles: List[int]
        :type h: int
        :rtype: int
        """
        #k The conditions for meeting the requirements are :piles[i]/k  Less than or equal to 8
        def check(k):
            total_cnt=0
            for i in range(len(piles)):
                cnt=piles[i]//k
                if piles[i]%k>0:
                    cnt+=1
                total_cnt+=cnt 
            if total_cnt<=h:
                return True
            return False
                
        left=0
        right=10**9
        while left<right:
            mid=(left+right)//2
            if mid==0:
                return 1
            if check(mid):
                right=mid 
            else:
                left=mid+1
        return left

Use the way of adding and subtracting one to everything

class Solution(object):
    def minEatingSpeed(self, piles, h):
        """
        :type piles: List[int]
        :type h: int
        :rtype: int
        """
        def check(x):
            count = 0
            for i in range(len(piles)):
                if piles[i] % x == 0:
                    count += piles[i] // x
                else:
                    count += piles[i] // x + 1
            if count <= h:
                return True
            else:
                return False
        left = 1
        right = sum(piles)
        while left <= right:
            mid = (left + right) // 2
            # You can eat all the bananas 
            if check(mid):
                right = mid -1 
            else:
                left = mid + 1
        return right + 1

2080. The frequency of querying numbers in the interval

 

  Two points , Find the upper and lower bounds

class RangeFreqQuery {

    Map<Integer, List<Integer>> map = new HashMap<>();
    public RangeFreqQuery(int[] arr) {
        int n = arr.length;
        for(int i = 0; i < n; i++){
            List<Integer> tmp = map.getOrDefault(arr[i], new ArrayList<>());
            tmp.add(i);
            map.put(arr[i], tmp);
        }
    }
    
    public int query(int left, int right, int value) {
        if(!map.containsKey(value)) return 0;
        int l = lower_bound(map.get(value), left);
        int r = upper_bound(map.get(value), right);
        return r - l;
    }
    public int lower_bound(List<Integer> a, int target){
        int n = a.size();
        int l = 0, r = n;
        while(l < r){
            int mid = (l + r) >> 1;
            if(target <= a.get(mid)) r = mid;
            else l = mid + 1;
        }
        return l;
    }
    public int upper_bound(List<Integer> a, int target){
        int n = a.size();
        int l = 0, r = n;
        while(l < r){
            int mid = (l + r) >> 1;
            if(target >= a.get(mid)) l = mid + 1;
            else r = mid;
        }
        return l;
    }
}

 author :LCS_0215
 link :https://leetcode-cn.com/problems/range-frequency-queries/solution/ha-xi-biao-er-fen-si-chong-chang-yong-er-nwop/
 source : Power button (LeetCode)
 The copyright belongs to the author . Commercial reprint please contact the author for authorization , Non-commercial reprint please indicate the source .
class RangeFreqQuery(object):
    def __init__(self, arr):
        """
        :type arr: List[int]
        """
        # Record the subscript of each element 
        self.value_indexs=collections.defaultdict(list)
        for i in range(len(arr)):
            self.value_indexs[arr[i]].append(i)
    def query(self, left, right, value):
        """
        :type left: int
        :type right: int
        :type value: int
        :rtype: int
        """
        value_index =self.value_indexs[value]
        #value index It is arranged from small to large ,
        # for example  value index= [2,4,6].left=3,right=5
        cnt=0
        for i in value_index:
            if i>=left and i<=right:
                cnt+=1
        return cnt
# Your RangeFreqQuery object will be instantiated and called as such:
# obj = RangeFreqQuery(arr)
# param_1 = obj.query(left,right,value)

1060. Missing elements in an ordered array

  Be careful

if diff[mid] >= k:
    right = mid

Have an equal sign , Otherwise, there are case will not pass . for example

nums = [4,7,9,10]
# nums = [1,2,4]
k = 3

diff=[0, 2, 3, 3]. We have to find the first one 3 .

class Solution:
    def missingElement(self, nums: List[int], k: int) -> int:
        # Find out diff
        diff=[0 for _ in range(len(nums))]
        for i in range(1,len(nums)):
            diff[i]=(nums[i]-nums[i-1]-1)+diff[i-1]
            # if diff[i]>=k:
            #     return nums[i-1]+(k-diff[i-1])
        if k>diff[-1]:
            return  nums[-1]+(k-diff[-1])
        
        # Search in two k The location of 
        left=0
        right=len(nums)
        while left<right:
            mid=(left+right)//2
            if diff[mid]>=k:
                right=mid 
            else:
                left=mid+1
        return nums[left-1]+(k-diff[left-1])

1182. The shortest distance from the target color

  The board is divided into two parts

use

if left-1>=0:

a2=abs(indexs[left-1]-index)

res.append(min(a1,a2))

To determine whether it is in the front or behind

class Solution:
    def shortestDistanceColor(self, colors: List[int], queries: List[List[int]]) -> List[int]:
       # Save the index of the element as list
        from collections import defaultdict
        value_index=defaultdict(list)
        for i in range(len(colors)):
            value_index[colors[i]].append(i)
        res=[]
        for i in range(len(queries)):
            index=queries[i][0]
            target=queries[i][1]
            if target not in value_index:
                res.append(-1)
            else:
                indexs=value_index[target]
                #target and indexs The shortest distance between 
                left=0
                right=len(indexs)-1
                while left<right:
                    mid=(left+right)//2
                    if indexs[mid]>=index:
                        right=mid
                    else:
                        left=mid+1
                a1=abs(indexs[left]-index)
                if left-1>=0:
                    a2=abs(indexs[left-1]-index)
                    res.append(min(a1,a2))
                else:
                    res.append(a1)
        return res

1231. Share the chocolate

  The difficulty of this question is how to judge whether it meets the conditions ,check function , I don't want to .

class Solution(object):
    def maximizeSweetness(self, sweetness, k):
        """
        :type sweetness: List[int]
        :type k: int
        :rtype: int
        """
        def check(thres):
            ans = 0
            sub_sweetness = 0
            for i in range(len(sweetness)):
                sub_sweetness += sweetness[i]
                if sub_sweetness >= thres:
                    ans += 1
                    sub_sweetness = 0

            return ans > k
        
        left, right = 1, sum(sweetness)

        while left < right:
            mid = left + ((right - left + 1) >> 1)
            if check(mid):
                left = mid
            else:
                right = mid - 1
        
        return left

 author :mangoooosteen
 link :https://leetcode-cn.com/problems/divide-chocolate/solution/python-er-fen-cha-zhao-by-mangoooosteen-rvz8/
 source : Power button (LeetCode)
 The copyright belongs to the author . Commercial reprint please contact the author for authorization , Non-commercial reprint please indicate the source .
class Solution:
    def maximizeSweetness(self, sweetness: List[int], k: int) -> int:
        def check(index):
            ans=0
            count=0
            for i in range(len(sweetness)):
                count=count+sweetness[i]
                if count>=index:
                    ans+=1
                    count=0 
            if ans>=k+1:
                return True
            return False
                
        left=1
        right=sum(sweetness)
        while left<=right:
            mid=(left+right)//2
            if check(mid):
                left=mid+1
            else:
                right=mid-1
        return left-1

287 Look for repetitions

Dichotomize the range

const findDuplicate = (nums) => {
    let lo = 1;
    let hi = nums.length - 1; // The title indicates :nums.length == n + 1
    while (lo < hi) {
        const mid = (lo + hi) >>> 1;  //  Find the middle index 
        let count = 0;
        for (let i = 0; i < nums.length; i++) {
            if (nums[i] <= mid) {
                count++;
            }
        }
        if (count > mid) {
            hi = mid;
        } else {
            lo = mid + 1;
        }
    }
    return lo;
};

 author :xiao_ben_zhu
 link :https://leetcode-cn.com/problems/find-the-duplicate-number/solution/zhe-ge-shu-zu-you-dian-te-shu-suo-yi-ke-yi-yong-ku/
 source : Power button (LeetCode)
 The copyright belongs to the author . Commercial reprint please contact the author for authorization , Non-commercial reprint please indicate the source .

【LeetCode- lookup 】 Look for repetitions - Flix - Blog Garden

How to write it 1 

class Solution {
public:
    int findDuplicate(vector<int>& nums) {
        int left = 1;
        int right = nums.size()-1;
        while(left<right){
            int mid = left+(right-left)/2;
            int cnt = 0;
            for(int num:nums){
                if(num<=mid) cnt++;
            }

            if(cnt>mid){
                right = mid; //  Because the cyclic condition is left<right, So this is  right=mid;
            }else{
                left = mid+1;
            }
        }
        return left;
    }
};

How to write it 2

class Solution {
public:
    int findDuplicate(vector<int>& nums) {
        int left = 1;
        int right = nums.size()-1;
        while(left<=right){
            int mid = left+(right-left)/2;
            int cnt = 0;
            for(int num:nums){
                if(num<=mid) cnt++;
            }

            if(cnt>mid){
                right = mid-1;
            }else{
                left = mid+1;
            }
        }
        return left;
    }
};

The same as cocoa, which likes bananas

Power button

class Solution:
    def findDuplicate(self, nums: List[int]) -> int:
        def check(x):
            count = 0
            for i in range(len(nums)):
                if nums[i] < x:
                    count += 1
            if count < x:
                return True
            return False

        left = 1
        right = len(nums) - 1
        while left <= right:
            mid = (left + right) // 2
            if check(mid):
                left = mid + 1
            else:
                right = mid - 1
        # The last satisfaction check Conditions of the mid, yes left - 1
        return left - 1

540. A single element in an ordered array

Parity dichotomy  

class Solution {
    public int singleNonDuplicate(int[] nums) {
        int n = nums.length;
        int l = 0, r = n - 1;
        while (l < r) {
            int mid = l + r >> 1;
            if (mid % 2 == 0) {
                if (mid + 1 < n && nums[mid] == nums[mid + 1]) l = mid + 1;
                else r = mid;
            } else {
                if (mid - 1 >= 0 && nums[mid - 1] == nums[mid]) l = mid + 1;
                else r = mid;
            }
        }
        return nums[r];
    }
}

 author :AC_OIer
 link :https://leetcode-cn.com/problems/single-element-in-a-sorted-array/solution/gong-shui-san-xie-er-duan-xing-fen-xi-yu-17nv/
 source : Power button (LeetCode)
 The copyright belongs to the author . Commercial reprint please contact the author for authorization , Non-commercial reprint please indicate the source .

410. The maximum value of the split array

6068. The maximum number of white bricks covered by the blanket

  Two points to find the boundary

Similar questions are :

436. Look for the right range

2055. Candles between plates

class Solution:
    def maximumWhiteTiles(self, tiles: List[List[int]], carpetLen: int) -> int:
        
        n = len(tiles)
        tiles.sort()                                #  Sort 
        
        nums = [t[1] for t in tiles]                #  The right end of the tile section 
        presum = [r - l +1 for (l,r) in tiles]      #  The prefix and 
        presum = list(itertools.accumulate(presum))
        
        ans = 0
        for i, (left, _) in enumerate(tiles):       # left: The left end of the blanket ,right: Right end of blanket 
            right = left + carpetLen - 1
            j = bisect.bisect_right(nums, right)    #  Two point search 【 Search right 】
            
            cnt = presum[j-1] - (presum[i-1] if i >=1 else 0)   # [i, j-1] The tiles in the section are covered with blankets 
            if j <= n-1 and right >= tiles[j][0]:               # [j] The tiles in the section shall be judged separately :
                cnt += right - tiles[j][0] + 1                  #  The right end of the blanket is [j] Within the interval 
            ans = max(ans, cnt)
        
        return ans

 author :flix
 link :https://leetcode.cn/problems/maximum-white-tiles-covered-by-a-carpet/solution/by-flix-zoqe/
 source : Power button (LeetCode)
 The copyright belongs to the author . Commercial reprint please contact the author for authorization , Non-commercial reprint please indicate the source .

原网站

版权声明
本文为[Linchong Fengxue mountain temple]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/173/202206221230105608.html