Learning to find two points in three problems -- solving problems in java, python and c ( ̄▽  ̄)~*

Posted by kelvin on Mon, 20 Dec 2021 11:18:43 +0100

Binary search

Binary search is usually applied to an ordered array. It is an algorithm that divides the search space into two after each comparison.

Terms used in binary search:

Target: target. The value you want to find
Index: index. The current location you want to find
Left, Right: left and Right indicators (which can be understood as the subscripts corresponding to the left and Right endpoints of a closed interval). We use them to maintain the index of search space
Mid: middle indicator (the index of the middle position calculated according to the index of the left and right endpoints). We use conditions to determine whether we should look left or right.

Question 1: basic questions (template)

Given an n-element ordered (ascending) integer array nums and a target value target, write a function to search the target in nums. If the target value exists, return the subscript, otherwise return - 1.

Example:

Input: num = [- 1,0,3,5,9,12], target = 9
Output: 4
Explanation: 9 appears in nums and the subscript is 4

Tips:
You can assume that all elements in nums are not repeated.
n will be between [1, 10000].
Each element of num will be between [- 9999, 9999].

Source: LeetCode
Link: https://leetcode-cn.com/problems/binary-search

(the following code has detailed comments)

java

public class BinarySearch704 {

	//Define nums array, and target value
	public int search(int[] nums, int target) {
		int left = 0;//Leftmost subscript
		int right = nums.length-1;//Subscript of rightmost number
		//Remember to bring an equal sign when judging the while condition
		while(left<=right) {
			//Find the middle position and judge whether the value corresponding to this position is equal to target
			int mid = left +(right - left)/2;
			if(nums[mid] == target) {
				return mid;
			}
			//If the target value is less than the middle position value, use this part to dichotomy again
			//It's easy to get confused about adding 1 minus 1. Remember that the subscript of the array starts from 0. If you can't, draw a picture
			else if(nums[mid] > target) {
				right = mid-1;
			}
			else {
				left = mid+1;
			}
		}
		return -1;
	}
}

python

# Method one dichotomy, which is basically the same as java)
class Solution:
    def search(self, nums: List[int], target: int):
        left, right = 0, len(nums) - 1
        #left is 0 and right is len (nums) - 1
        while left <= right:
            mid = left + (right - left) // 2
            if nums[mid] == target:
                return mid
            if target < nums[mid]:
                right = mid - 1
            else:
                left = midt + 1
        return -1


# Method 2 (not dichotomy, less code, but slow operation)
from typing import List
class Solution:
    def search(self, nums: List[int], target: int):
        #Traversal, compare the number in target and num one by one
        if target in nums :
            return nums.index(target)
        # The Python index() method detects whether the string contains a substring str. if beg (start) and
        # End (end) range, check whether it is included in the specified range. This method is the same as python find() method,
        # But if str is not in the string, an exception will be reported.
        else:
            return -1

C

#include <stdio.h>
int search(int* nums, int numsSize, int target){
{
	int first = 0,last = numsSize-1,mid;
	while(first <= last)
	{
		mid = first + (last - first) / 2;//Identify intermediate elements	
		if(nums[mid] > target)
		{
			last = mid-1; //mid has been swapped. last moves forward one bit
		}
		else if(nums[mid] < target)
		{
			first = mid+1;//mid has been exchanged. first moves back one bit
		}	
		else //Judge whether they are equal
		{
			return mid;
		}
	}
	return -1;
}

The above code is basically the most basic template for binary search.

Difficulties of dichotomy

At present, dichotomy is not difficult at all, but its details are extremely error prone.
Does the while loop have an equal sign
right and left are plus one and minus one
These details vary with the meaning of the topic

Question 2 (the question is a little windy)

You are a product manager and are currently leading a team to develop new products. Unfortunately, the latest version of your product has not passed the quality test. Since each version is developed based on the previous version, all versions after the wrong version are wrong.
Suppose you have n versions [1, 2,..., n], you want to find the first wrong version that causes errors in all subsequent versions.
You can call the bool isBadVersion(version) interface to determine whether the version number is wrong in the unit test. Implement a function to find the first wrong version. You should minimize the number of calls to the API.

Example:

Input: n = 5, bad = 4
Output: 4
Explanation:
Call isbadversion (3) - > false
Call isbadversion (5) - > true
Call isbadversion (4) - > true
So, 4 is the first wrong version.

Tips:
1 <= bad <= n <= 231 - 1

Source: LeetCode
Link: https://leetcode-cn.com/problems/first-bad-version

Analyze the meaning of the topic

In fact, it is also a search problem in an ordered array. And we need to "minimize the number of calls to the API", so we still use the dichotomy.

Then look at the example. isBadVersion is used to judge whether the version is a bad version. Therefore, if the result is false, the version is a good version.

java

public class FirstWrongVersion278 {
    public int firstBadVersion(int n) {
    	// If you want to understand the questions, you should still take the dichotomy test
    	// It is not an array. You can use subscripts from the beginning, which is more in line with language habits
        int left = 1;
        int right = n;
        // Stop the loop when the two are equal, so the while condition does not add an equal sign this time
        while(left < right) {
        	int mid = left + (right-left)/2;
        	if(isBadVersion(mid)) {
        		// Because this mid is likely to be the first wrong, don't subtract one and let it be included in the interval again
        		right = mid;// The answer is in the interval [left, mid]
        	}else {
        	//At this time, this version is correct and needs to be looked for later
        	//This version does not need to be included in the interval
        		left = mid + 1;
        	}
        }
     return right;   	
    }
}

python

class Solution:
    def firstBadVersion(self, n):
        """
        :type n: int
        :rtype: int
        """
        left = 0
        right = n
        while(left<right):
            mid = left + (right - left)//2
            if isBadVersion(mid):
                right = mid
            else:
                left = mid+1
        return right

C

int firstBadVersion(int n) {
    int left = 1, right = n;
    while (left < right) {  // Cycle until the left and right end points of the interval are the same
        int mid = left + (right - left) / 2;  // Prevent overflow during calculation
        if (isBadVersion(mid)) {
            right = mid;  // The answer is in the interval [left, mid]
        } else {
            left = mid + 1;  // The answer is in the interval [mid+1, right]
        }
    }
    // At this time, there is left == right, and the interval is reduced to a point, which is the answer
    return left;
}

Question 3 (still very simple)

Given a sort array and a target value, find the target value in the array and return its index. If the target value does not exist in the array, returns the position where it will be inserted in order.

You must use an algorithm with a time complexity of O(log n).

Example:

Input: num = [1,3,5,6], target = 7
Output: 4

Input: num = [1,3,5,6], target = 0
Output: 0

Input: num = [1], target = 0
Output: 0

Tips:

1 <= nums.length <= 104
-104 <= nums[i] <= 104
nums is an ascending array without repeating elements
-104 <= target <= 104

Source: LeetCode
Link: https://leetcode-cn.com/problems/search-insert-position

java

public class SearchInsertionLocation35 {
    public int searchInsert(int[] nums, int target) {

    	//You can still use dichotomy
    	int left = 0;
    	int right = nums.length-1;
    	while(left <= right) {
    		int mid = left + (right - left)/2;
    		if(nums[mid] == target ) {
    			return mid;
    		}
    		else if(nums[mid] < target) {
    			left = mid + 1;
    		}
    		else {
    			right = mid - 1;
    		}
    	}
    	return left;
    	
    }

}

python

class Solution:
    def searchInsert(self, nums: List[int], target: int) -> int:
        left = 0
        right =len(nums)-1
        while(left <= right):
            mid = left + (right - left)//2
            if(nums[mid] == target ):
                return mid
            elif(nums[mid] < target):
                left = mid + 1
            else:
                right = mid - 1
        return left

C

int searchInsert(int* nums, int numsSize, int target){

    int left = 0, right = numsSize - 1, ans = numsSize;
    while (left <= right) {
        int mid = ((right - left) >> 1) + left;
        //Mid = (left + right) > > 1
		//Shift right operator > >, the operation result can exactly correspond to the half value of an integer, which can just replace the mathematical Division 2 operation,
		//But it's faster than dividing by two.
		//Mid = (left + right) > > 1 is equivalent to mid=(left+right)/2 
        if (target <= nums[mid]) {
            ans = mid;
            right = mid - 1;
        } else {
            left = mid + 1;
        }
    }
    return ans;
}

Topics: Python Java Algorithm data structure leetcode