leetcode 29 ~ 39

Leetcode 29

⭐⭐

题目描述

Given two integers dividend and divisor, divide two integers without using multiplication, division, and mod operator.

Return the quotient after dividing dividend by divisor.

The integer division should truncate toward zero, which means losing its fractional part. For example, truncate(8.345) = 8 and truncate(-2.7335) = -2.

示例

Example 1:

Input: dividend = 10, divisor = 3
Output: 3
Explanation: 10/3 =truncate(3.33333…) = 3.

Example 2:

Input: dividend = 7, divisor = -3
Output: -2
Explanation: 7/-3 = truncate(-2.33333…) = -2.

思路

关于如何提高效率快速逼近结果
举个例子:11 除以 3 。
首先11比3大,结果至少是1, 然后我让3翻倍,就是6,发现11比3翻倍后还要大,那么结果就至少是2了,那我让这个6再翻倍,得12,11不比12大,吓死我了,差点让就让刚才的最小解2也翻倍得到4了。但是我知道最终结果肯定在2和4之间。也就是说2再加上某个数,这个数是多少呢?我让11减去刚才最后一次的结果6,剩下5,我们计算5是3的几倍,也就是除法,看,递归出现了。
(这是一种二分的思路)

class Solution {
public:
    int divide(int dividend, int divisor) {
        if(divisor == 1) return dividend;
        if(divisor == -1){
            if(dividend>INT_MIN) return -dividend;// 只要不是最小的那个整数,都是直接返回相反数就好啦
            return INT_MAX;// 是最小的那个,那就返回最大的整数啦
        }
        long a = dividend;
        long b = divisor;
        int sign = 1;
        if((a>0&&b<0) || (a<0&&b>0)){
            sign = -1;
        }
        a = a>0?a:-a;
        b = b>0?b:-b;
        long res = div(a,b); //recursion
        if(sign>0)return res>INT_MAX?INT_MAX:res;
        return -res;
    }
    int div(long a, long b){  // 似乎精髓和难点就在于下面这几句
        if(a<b) return 0;
        long count = 1; // track the answer
        long accumulate_sum = b; // track the accumulate sum
        while((accumulate_sum+accumulate_sum)<=a){
            count = count + count; // 最小解翻倍
            accumulate_sum = accumulate_sum+accumulate_sum; // 当前测试的值也翻倍
        }
        return count + div(a-accumulate_sum,b);
    }
};

在这里插入图片描述

Leetcode 31 next permutation

⭐⭐

题目描述

Implement next permutation, which rearranges numbers into the lexicographically next greater permutation of numbers.

If such an arrangement is not possible, it must rearrange it as the lowest possible order (i.e., sorted in ascending order).

The replacement must be in place and use only constant extra memory.

示例

Example 1:

Input: nums = [1,2,3]
Output: [1,3,2]

Example 2:

Input: nums = [3,2,1]
Output: [1,2,3]

Example 3:

Input: nums = [1,1,5]
Output: [1,5,1]

思路

我们希望下一个数比当前数大,这样才满足“下一个排列”的定义。因此只需要将后面的「大数」前面的「小数」 交换,就能得到一个更大的数。比如 123456,将 5 和 6 交换就能得到一个更大的数 123465。

我们还希望下一个数增加的幅度尽可能的小,这样才满足“下一个排列与当前排列紧邻“的要求。为了满足这个要求,我们需要:

  1. 尽可能靠右的低位进行交换,需要从后向前查找
    将一个小数(A[i] < A[i+1])。比如 123465,这个小数应该是4. 此时,A[i+1]之后应该是降序排列的。
  2. 找到尽可能小的大数。从后向前找到第一个比小数大的数,就是我们要找的大数。比如 123465,这个大数应该是5.

交换 5 和 4,得到 123564;然后需要将 5 之后的数重置为升序,得到 123546。显然 123546 比 123564 更小,123546 就是 123465 的下一个排列。

以上就是求“下一个排列”的分析过程。

以求 12385764 的下一个排列为例:
在这里插入图片描述
首先从后向前查找第一个相邻升序的元素对 (i,j)。这里 i=4,j=5,对应的值为 5,7:
在这里插入图片描述
交换之。
在这里插入图片描述
这时 [j,end) 必然是降序,逆置 [j,end),使其升序。这里逆置 [7,5,4]:
在这里插入图片描述

class Solution {
public:
    void nextPermutation(vector<int>& nums) {
        int small_right = -1; // the small number as right as possible
        int big_left = 0;
        for(int i = nums.size()-1;i > 0; i--){//find the small number
            if(nums[i-1] < nums[i]) {
                small_right = i - 1;
                break;
            }
        }
        if(small_right == -1) { //if is already the biggest one, it has to be in descend order
            std::reverse(nums.begin(), nums.end());
            return;
        }
        for(int i = nums.size()-1; i >= small_right; i--){// find the big number
            if(nums[i] > nums[small_right]) {
                big_left = i;
                break;
            }
        }
        cout<<small_right<<" "<<big_left<<endl;
        swap(nums[small_right],nums[big_left]);
        std::reverse(nums.begin() + small_right + 1, nums.end());
    }
};

❗ 注意
在<algorithm>库中,有std::reverse函数,输入为iterator
std::reverse(nums.begin() + small_right + 1, nums.end())

Leetcode 33 - 35: Binary Search Specialization

Leetcode 35: Search Insert Position

难度: ⭐

Given a sorted array of distinct integers and a target value, return the index if the target is found. If not, return the index where it would be if it were inserted in order.

Example 1:

Input: nums = [1,3,5,6], target = 5
Output: 2

Example 2:

Input: nums = [1,3,5,6], target = 2
Output: 1

思路

这是一个基础的二分查找,只不过在基础的二分查找中,如果找不到就直接返回-1,在这里我们需要返回待插入的位置,这稍微需要动一些脑筋。其实,只需要在target比当前位置的值小的时候保留当前位置,最后指向的就是需要插入的位置了。

class Solution {
public:
    int searchInsert(vector<int>& nums, int target) {
        if(target > nums[nums.size()-1])
            return nums.size();

        int begin = 0;
        int end = nums.size()-1;
        int middle;
        int ans = end; //缺省值
        while(begin <= end){
            middle = begin + (end - begin) / 2;
            if(nums[middle] == target)
                return middle;
            if(nums[middle] < target){
                begin = middle + 1;
            }
            else { // nums[middle] > target
                end = middle - 1;
                ans = middle;
            }
        }
        return ans;
    }
};
leetcode 34. Find First and Last Position of Element in Sorted Array

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?

Example 1:

Input: nums = [5,7,7,8,8,10], target = 8
Output: [3,4]

Example 2:

Input: nums = [5,7,7,8,8,10], target = 6
Output: [-1,-1]

要想找到一个数(比如8)的开始位置和结束位置,我们可以找到7.5应该插入到何处,以及8.5可以插入到何处。这样就可以直接调用上一题的接口了!

class Solution(object):
    def searchRange(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: List[int]
        """
        if self.binarySearch(nums,0,len(nums)-1,target)[0] == 0:
            return [-1,-1]
        left = self.binarySearch(nums,0,len(nums)-1,target-0.5)[1]
        right = self.binarySearch(nums,0,len(nums)-1,target+0.5)[1]
        return [left,right-1]
    def binarySearch(self,nums,begin, end, target):
        ans = end + 1
        while(begin <= end):
            middle = (begin + end) // 2
            if nums[middle] == target:
                return [1,middle] ## 1代表找到了
            if nums[middle] < target:
                begin = middle + 1

            if nums[middle] > target:
                end = middle - 1
                ans = middle
        return [0,ans] ##0代表没找到
leetcode 33. Search in Rotated Sorted Array

There is an integer array nums sorted in ascending order (with distinct values).

Prior to being passed to your function, nums is rotated at an unknown pivot index k (0 <= k < nums.length) such that the resulting array is [nums[k], nums[k+1], …, nums[n-1], nums[0], nums[1], …, nums[k-1]] (0-indexed). 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].

Given the array nums after the rotation and an integer target, return the index of target if it is in nums, or -1 if it is not in nums.

Example 1:

Input: nums = [4,5,6,7,0,1,2], target = 0
Output: 4

Example 2:

Input: nums = [4,5,6,7,0,1,2], target = 3
Output: -1

思路

先找到分割点,判断target是在左边还是右边,然后到对应区域寻找。

class Solution(object):
    def search(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: int
        """
        for i in range(0,len(nums)):
            if nums[i] < nums[i-1]:
                break
        seperate = i
        if target == nums[-1]:
            return len(nums) - 1
        if target > nums[-1]:
            return self.binary_search(nums,0,i,target)
        if target < nums[-1]:
            return self.binary_search(nums, i, len(nums),target)

    def binary_search(self, nums, begin, end, target):
        while(begin < end):
            middle = (begin + end) // 2
            if(nums[middle] == target):
                return middle
            if(nums[middle] < target):
                begin = middle + 1
            else:
                end = middle
        return -1
leetcode 36. Valid Sudoku

Determine if a 9 x 9 Sudoku board is valid. Only the filled cells need to be validated according to the following rules:

Each row must contain the digits 1-9 without repetition.
Each column must contain the digits 1-9 without repetition.
Each of the nine 3 x 3 sub-boxes of the grid must contain the digits 1-9 without repetition.

Note:

A Sudoku board (partially filled) could be valid but is not necessarily solvable.
Only the filled cells need to be validated according to the mentioned rules.

Example 1:

Input: board =
[[“5”,“3”,".",".",“7”,".",".",".","."]
,[“6”,".",".",“1”,“9”,“5”,".",".","."]
,[".",“9”,“8”,".",".",".",".",“6”,"."]
,[“8”,".",".",".",“6”,".",".",".",“3”]
,[“4”,".",".",“8”,".",“3”,".",".",“1”]
,[“7”,".",".",".",“2”,".",".",".",“6”]
,[".",“6”,".",".",".",".",“2”,“8”,"."]
,[".",".",".",“4”,“1”,“9”,".",".",“5”]
,[".",".",".",".",“8”,".",".",“7”,“9”]]
Output: true

思路

一个简单的解决方案是遍历该 9 x 9 数独 三 次,以确保:
行中没有重复的数字。
列中没有重复的数字。
3 x 3 子数独内没有重复的数字。

实际上,所有这一切都可以在一次迭代中完成。
首先,让我们来讨论下面两个问题:

如何枚举子数独?
可以使用 box_index = (row / 3) * 3 + columns / 3,其中 / 是整数除法。来判断一个点属于哪个box
在这里插入图片描述
建立哈希映射:
rows[0]={},rows[1] = {},…rows[8] = {}
column[0] = {}, column[1] = {},…column[8] = {},
box[0]= {}, box[1] = {},…box[8] = {}
每个字典都不能出现重复。

leetcode 39. Combination Sum

Given an array of distinct integers candidates and a target integer target, return a list of all unique combinations of candidates where the chosen numbers sum to target. You may return the combinations in any order.

The same number may be chosen from candidates an unlimited number of times. Two combinations are unique if the frequency of at least one of the chosen numbers is different.

It is guaranteed that the number of unique combinations that sum up to target is less than 150 combinations for the given input.

Example 1:

Input: candidates = [2,3,6,7], target = 7
Output: [[2,2,3],[7]]

Example 2:

Input: candidates = [2,3,5], target = 8
Output: [[2,2,2,2],[2,3,3],[3,5]]

思路

It’s permutation all over again! 只不过,和全排列不同的是,这里可以重复的选。思路是,对于candidate的每一个位置,都可以选择是加入它、还是跳过它。如果选择加入它,就要进入递归。

class Solution(object):
    ans_list = []
    answ = []
    def combinationSum(self, candidates, target):
        """
        :type candidates: List[int]
        :type target: int
        :rtype: List[List[int]]
        """
        self.ans_list = []
        self.answ = []
        self.DFS(candidates,target,0)
        return self.ans_list


    def DFS(self, candidates, target, idx):
        if target == 0: # that is the answer!
            self.ans_list.append(self.answ)
            return
        if target < 0 or idx >= len(candidates):
            return
       
        self.DFS(candidates,target,idx+1) ##skip it!
        if(candidates[idx] <= target):
            self.answ.append(candidates[idx])#add it
            self.DFS(candidates,target-candidates[idx],idx)
            self.answ = self.answ[:-1]

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值