LeetCode 数学专题

268. Missing Number

Given an array containing n distinct numbers taken from 0, 1, 2, …, n, find the one that is missing from the array.

Example 1:

Input: [3,0,1]
Output: 2
Example 2:

Input: [9,6,4,2,3,5,7,0,1]
Output: 8
Note:
Your algorithm should run in linear runtime complexity. Could you implement it using only constant extra space complexity?

  • 思路

如果常数空间复杂度,可以用求和思想。

class Solution {
public:
    int missingNumber(vector<int>& nums) {
        int res = nums.size()*(nums.size()+1)/2;
        for(auto item:nums) res -= item;
        return res;
    }
};

62. Unique Paths

A robot is located at the top-left corner of a m x n grid (marked ‘Start’ in the diagram below).

The robot can only move either down or right at any point in time. The robot is trying to reach the bottom-right corner of the grid (marked ‘Finish’ in the diagram below).

How many possible unique paths are there?

Above is a 7 x 3 grid. How many possible unique paths are there?

Example 1:

Input: m = 3, n = 2
Output: 3
Explanation:
From the top-left corner, there are a total of 3 ways to reach the bottom-right corner:

  1. Right -> Right -> Down
  2. Right -> Down -> Right
  3. Down -> Right -> Right
    Example 2:

Input: m = 7, n = 3
Output: 28

Constraints:

1 <= m, n <= 100
It’s guaranteed that the answer will be less than or equal to 2 * 10 ^ 9.

  • 思路

简单的动态规划问题。

class Solution {
public:
    int uniquePaths(int m, int n) {
        int dp[110][110];
        memset(dp,sizeof dp,0);
        for(int i=0;i<110;i++) dp[i][0] = 1;
        for(int i=0;i<110;i++) dp[0][i] = 1;
        for(int i=1;i<m;i++)
            for(int j=1;j<n;j++)
                dp[i][j] = dp[i-1][j] + dp[i][j-1];
        return dp[m-1][n-1];
    }
};

还有一种组合数学的方法,其实结果就为C(n-1,m+n-2),即在总步数m+n-2中选择任意n-1步向着同一个方向。

记住求C(n-1,m+n-2),就想像自己在求杨辉三角!

class Solution {
public:
    int dp[110][110];
    int c(int m,int n){
        if(m == n || n == 0) return 1;
        if(dp[m][n] == 0) dp[m][n] = c(m-1,n) + c(m-1,n-1);
        return dp[m][n];
    }

    int uniquePaths(int m, int n) {
        return c(m+n-2,n-1);
    }
};

462. Minimum Moves to Equal Array Elements II – important

Given a non-empty integer array, find the minimum number of moves required to make all array elements equal, where a move is incrementing a selected element by 1 or decrementing a selected element by 1.

You may assume the array’s length is at most 10,000.

Example:

Input:
[1,2,3]

Output:
2

Explanation:
Only two moves are needed (remember each move increments or decrements one element):

[1,2,3] => [2,2,3] => [2,2,2]

  • 思路

这里关键是如何选取要变化的目标值。

可以画图看,两个数的话目标值必定在两数之间才可以保证操作次数最小。

那么对于一组数,可以排序后最大值和最小值一组,第二大值和第二小值一组。。。如果保证每组操作次数都最小,那么最终结果也就最小。

因此目标值就是中位数!

class Solution {
public:
    int minMoves2(vector<int>& nums) {
        sort(nums.begin(),nums.end());
        int mid = nums[nums.size()>>1];
        if(!nums.size()&1) mid = (mid + nums[nums.size()>>1-1])/2;
        
        int res = 0;
        for(auto item:nums) res += abs(item-mid);
        return res;
    }
};

458. Poor Pigs – important

There are 1000 buckets, one and only one of them is poisonous, while the rest are filled with water. They all look identical. If a pig drinks the poison it will die within 15 minutes. What is the minimum amount of pigs you need to figure out which bucket is poisonous within one hour?

Answer this question, and write an algorithm for the general case.

General case:

If there are n buckets and a pig drinking poison will die within m minutes, how many pigs (x) you need to figure out the poisonous bucket within p minutes? There is exactly one bucket with poison.

Note:

A pig can be allowed to drink simultaneously on as many buckets as one would like, and the feeding takes no time.
After a pig has instantly finished drinking buckets, there has to be a cool down time of m minutes. During this time, only observation is allowed and no feedings at all.
Any given bucket can be sampled an infinite number of times (by an unlimited number of pigs).

  • 思路

参考了评论大神的思路。对于两个小猪,喝完毒药15min 死去,在1h最多能检验多个水桶?答案是25桶,如下图所示:
在这里插入图片描述
对于一只猪,可以在1h之内最多喝 4次水(60/15),但是可以检验5个桶,如果前四次没死,说明第5个桶有毒。

对于2只猪,现在可以让一只猪一下喝5桶水,如图所示的一只猪喝的五个,一只猪喝的五个,这样就可以确定哪个桶有毒。

对于3只猪,就是三维的 5 X 5 X 5 ,可以检测125个桶。。。

class Solution {
public:
    int poorPigs(int buckets, int minutesToDie, int minutesToTest) {
        int pigs = 0;
        int d = minutesToTest / minutesToDie + 1;
        while(pow(d,pigs) < buckets) pigs ++;
        return pigs;
    }
};

319. Bulb Switcher

There are n bulbs that are initially off. You first turn on all the bulbs. Then, you turn off every second bulb. On the third round, you toggle every third bulb (turning on if it’s off or turning off if it’s on). For the i-th round, you toggle every i bulb. For the n-th round, you only toggle the last bulb. Find how many bulbs are on after n rounds.

Example:

Input: 3
Output: 1
Explanation:
At first, the three bulbs are [off, off, off].
After first round, the three bulbs are [on, on, on].
After second round, the three bulbs are [on, off, on].
After third round, the three bulbs are [on, off, off].

So you should return 1, because there is only one bulb is on.

  • 思路

每盏灯被按的次数就是编号的约数和。所以答案就是约数和为奇数的数。
而约数和为奇数的数就是平方数。所以问题转化为求1-n中的平方数个数。

而1-n中的平方数就是11,22,…,sqrt(n)*sqrt(n),那个数不就是sqrt(n)吗!

class Solution {
public:
    int bulbSwitch(int n) {
        return sqrt(n);
    }
};

343. Integer Break

Given a positive integer n, break it into the sum of at least two positive integers and maximize the product of those integers. Return the maximum product you can get.

Example 1:

Input: 2
Output: 1
Explanation: 2 = 1 + 1, 1 × 1 = 1.
Example 2:

Input: 10
Output: 36
Explanation: 10 = 3 + 3 + 4, 3 × 3 × 4 = 36.
Note: You may assume that n is not less than 2 and not larger than 58.

  • 思路

我还是无脑暴力流,当然还是用了dp数组保存了中间结果,因为当n<=4的时候结果是小于n的,所以特殊考虑。

其他一旦分到n<=4时,直接返回n。

class Solution {
public:
    int dp[100010];
    
    int integerBreakL(int n){
    	if(n <= 4) return n;
    	if(dp[n]) return dp[n];
        int res = 0;
        for(int i=1;i<n;i++) 
			res = max(res,integerBreakL(i) * integerBreakL(n-i));
        dp[n] = res;
        return res;
    }
    
    int integerBreak(int n) {
        if(n == 2) return 1;
        if(n == 3) return 2;
        if(n == 4) return 4;
        return integerBreakL(n);
    }
};

或者这样:

class Solution {
public:
    int dp[100010];
    int integerBreak(int n) {
        if(n == 2) return 1;
        if(n == 3) return 2;
        if(n == 4) return 4;
        for(int i=1;i<=4;i++) dp[i] = i;
        for(int i=5;i<=n;i++)
            for(int j=2;j<i;j++)
                dp[i] = max(dp[i],dp[j]*(i-j));
        return dp[n];
    }
};

评论大神的解法(咱们用点正常算法行不 orz)。求函数 y=(n/x)x(x>0) 的最大值,可得x=e时y最大,但只能分解成整数,故x取2或3,由于6=2+2+2=3+3,显然23=8<9=32,故应分解为多个3。

class Solution {
public:
	int integerBreak(int n) {
	    if(n == 2) return 1;
	    if(n == 3) return 2;
	    int a = 1;
	    while(n > 4){
	        n = n - 3;
	        a = a * 3;
	    }
	    return a * n;
	}
};

650. 2 Keys Keyboard – important

Initially on a notepad only one character ‘A’ is present. You can perform two operations on this notepad for each step:

Copy All: You can copy all the characters present on the notepad (partial copy is not allowed).
Paste: You can paste the characters which are copied last time.

Given a number n. You have to get exactly n ‘A’ on the notepad by performing the minimum number of steps permitted. Output the minimum number of steps to get n ‘A’.

Example 1:

Input: 3
Output: 3
Explanation:
Intitally, we have one character ‘A’.
In step 1, we use Copy All operation.
In step 2, we use Paste operation to get ‘AA’.
In step 3, we use Paste operation to get ‘AAA’.

Note:

The n will be in the range [1, 1000].

  • 思路

再次硬钢。/_ \

class Solution {
public:
    int res = 99999999;
    void minStepsL(int n,int nowPaste,int nowChar,int tempStep){
        if(nowChar == n){
            res = min(res,tempStep);
            return;
        } 
        if(nowChar > n || nowPaste > n) return;
        if(nowPaste == 0) minStepsL(n,1,nowChar,tempStep+1);
        else{
        	// 复制粘贴
            minStepsL(n,nowChar,nowChar*2,tempStep+2);
            // 只粘贴
            minStepsL(n,nowPaste,nowChar+nowPaste,tempStep+1);
        } 
    }

    int minSteps(int n) {
        minStepsL(n,0,1,0);
        return res;
    }
};

看了大神评论没想到上面的代码还可以优化,优先复制粘贴,这样得到的一定是最优的!

class Solution {
public:
    int res;
    bool minStepsL(int n,int nowPaste,int nowChar,int tempStep){
        if(nowChar == n){
            res = tempStep;
            return true;
        }
        if(nowChar > n) return false;
        if(minStepsL(n,nowChar,nowChar*2,tempStep+2)) return true;
        return minStepsL(n,nowPaste,nowChar+nowPaste,tempStep+1);
    }

    int minSteps(int n) {
        minStepsL(n,0,1,0);
        return res;
    }
};

这道题的正确数学解法应该是(还是参考了评论大神的解法):

class Solution {
public:
    int minSteps(int n) {
        if (n == 1) return 0; // 1不用操作
        int maxfactor = 1;
        
        // 这里找出n大于1的最小公因数,打个比方
        // 18的最小公因数是3,那么只用把6经过三次操作就可以变成18了
        for (int i = 2; i <= sqrt(n); i++) {
            if (n%i == 0) {
                maxfactor = i;
                break;
            }
        }
        if (maxfactor == 1) return n; //maxfactor为1代表n是质数,质数没有公因式,直接返回本身就ok
        return maxfactor + minSteps(n / maxfactor);//还是拿18做例子,变成18所需要的次数=3+变成6所需要的次数。
        //变成6所需要的次数=2+变成3所需要的次数。
        //3是质数,直接返回3,所以答案就是3+2+3=8
    }
};

223. Rectangle Area

Find the total area covered by two rectilinear rectangles in a 2D plane.

Each rectangle is defined by its bottom left corner and top right corner as shown in the figure.

Rectangle Area

Example:

Input: A = -3, B = 0, C = 3, D = 4, E = 0, F = -1, G = 9, H = 2
Output: 45
Note:

Assume that the total area is never beyond the maximum possible value of int.

  • 思路
class Solution {
public:
    int computeArea(int A, int B, int C, int D, int E, int F, int G, int H) {
        int s1 = (A-C)*(B-D), s2 = (E-G)*(F-H);
        int topx = min(C,G), topy = min(D,H);
        int butx = max(A,E), buty = max(B,F);
        if(topx<butx || topy<buty) return s1+s2;
        int s3 = s1 - (topx-butx)*(topy-buty) + s2;
        return s3;
    }
};

829. Consecutive Numbers Sum – important

Given a positive integer N, how many ways can we write it as a sum of consecutive positive integers?

Example 1:

Input: 5
Output: 2
Explanation: 5 = 5 = 2 + 3
Example 2:

Input: 9
Output: 3
Explanation: 9 = 9 = 4 + 5 = 2 + 3 + 4
Example 3:

Input: 15
Output: 4
Explanation: 15 = 15 = 8 + 7 = 4 + 5 + 6 = 1 + 2 + 3 + 4 + 5
Note: 1 <= N <= 10 ^ 9.

  • 思路

继续暴力,不过这次是真的超时了!43156417 这个数据是真的过不了了!
双指针O(N2)的复杂度。(提前break了下,所以过了 130 / 170 个)

class Solution {
public:
    int consecutiveNumbersSum(int N) {
        int res = 0;
        for(int i=1;i<=N;i++)
            for(int j=i;j<=N;j++){
                int sum = 1ll*(i+j)*(j-i+1)/2;
                if(sum > N) break;
                if(sum == N) res++;
            }
        return res;
    }
};

891. Sum of Subsequence Widths

Given an array of integers A, consider all non-empty subsequences of A.

For any sequence S, let the width of S be the difference between the maximum and minimum element of S.

Return the sum of the widths of all subsequences of A.

As the answer may be very large, return the answer modulo 10^9 + 7.

Example 1:

Input: [2,1,3]
Output: 6
Explanation:
Subsequences are [1], [2], [3], [2,1], [2,3], [1,3], [2,1,3].
The corresponding widths are 0, 0, 0, 1, 1, 2, 2.
The sum of these widths is 6.

Note:

1 <= A.length <= 20000
1 <= A[i] <= 20000

  • 思路

完全没思路,参考大神的题解:
https://leetcode-cn.com/problems/sum-of-subsequence-widths/solution/pai-xu-shu-xue-by-lucifer1004/

class Solution {
public:
    const int N = 1e9+7;
    int sumSubseqWidths(vector<int>& A) {
        vector<int> vec(A.size()+1);
        vec[0] = 1;
        for(int i=1;i<=A.size();i++) vec[i] = (vec[i-1] << 1) % N;
        
        sort(A.begin(),A.end());
        int res = 0;
        for(int i=0;i<A.size();i++){
            int temp = vec[i] - vec[A.size()-i-1];
            res = (res + 1ll * temp * A[i] % N) % N;
        }
        return res;
    }
};
发布了46 篇原创文章 · 获赞 98 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/qq_40515692/article/details/105488349
今日推荐