LeetCode Learning 4

413. Arithmetic Slices
A sequence of number is called arithmetic if it consists of at least three elements and if the difference between any two consecutive elements is the same.


A zero-indexed array A consisting of N numbers is given. A slice of that array is any pair of integers (P, Q) such that 0 <= P < Q < N.


A slice (P, Q) of array A is called arithmetic if the sequence:
A[P], A[p + 1], ..., A[Q - 1], A[Q] is arithmetic. In particular, this means that P + 1 < Q.


The function should return the number of arithmetic slices in the array A.


这是一道难度为medium的题。大意为求一个数列中的等差切片的数量。我很快就想到了最naive的方法,切片至少包含3个连续的元素,则把每个3~n长的切片判断是否等差,最后再统计总数即可。代码如下:
class Solution {
public:
    bool ari(vector<int> A,int len,int bg){
        int d=A[bg+1]-A[bg];
        for(int k=1;k<len-1;k++){
            if(A[bg+k+1]-A[bg+k]!=d)return false;
        }
        return true;
    }
    int numberOfArithmeticSlices(vector<int>& A) {
        int n=A.size();
        int count=0;
        for(int len=3;len<n+1;len++){
            for(int bg=0;bg<n-len+1;bg++){
                if(ari(A,len,bg)) count++;
            }
        }
        return count;
    }
};



然而显然如此简单的方法不能达到medium的要求。。。这种方法其实做了很多多余的步骤去计算已经计算过的数字之差。而各相邻数字之差应该有办法只计算一次,扫一遍解决问题,这样就能在O(n)时间解决。我想到了生成一个大小=n的数组,用于存放以这个位置为结尾的等差切片的数量。这样在扫描时计算出每一项的这个值,最后全部加起来就是答案了。而要计算以此为结尾的等差切片数量其实很简单,只要看他之前有多少项是等差。然后从开始等差的位置到此位置的前2位都可以作为等差切片的开头位置,能作为开头位置的数量就是以这个位置为结尾的等差切片数量。具体代码如下:
int numberOfArithmeticSlices(vector<int>& A) {
	int n = A.size();
	if (n<3) return 0;
	vector<int> a(n, 0);
	int i, bg, d;
	//find the first slice
	for (i = 0; i<n; i++)
	{
		if (A[i + 2] - A[i + 1] == A[i + 1] - A[i]) {
			bg = i;
			d = A[i + 1] - A[i];
			break;
		}
	}
	for (i = i + 2; i<n; i++)
	{
		if (d == A[i] - A[i - 1]&&i-bg-1>0){
			a[i] = i - bg - 1;
		}
		else {
			bg = i - 1;
			d= A[i] - A[i - 1];
		}
	}
	int sum = 0;
	for (int i = 0; i<n; i++)
		sum += a[i];
	return sum;
}




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.


For example, given n = 2, return 1 (2 = 1 + 1); given n = 10, return 36 (10 = 3 + 3 + 4).


这道题实际上算是一道数学问题。利用高中所学的均值不等式可以知道一个正数拆分成k个正数时,拆分的数全部相等时他们的积取最大值。那么这道题只需要知道分成多少个数,那些数的大小是多少就可以得出答案了。


那么设每一个数为x,则一共有n/x个数。设它们的积为f(x),则f(x)=x^(n/x)。


f′(x)=(n/x2)  *  x(n/x)  * (1-lnx)
当x=e时取极大值。


而题意是分成整数,最接近e的是2和3,6=2+2+2=3+3,而2*2*2=8<3*3=9,则可得知把数都分成3时乘积最大。所以当n被3整除时,3^(n/3)就是最大乘积。若余1,则应拆成1个4其他都为3.若余2,则应拆成1个2其他都为3。这就是取得最大乘积的方法。代码如下:

 int integerBreak(int n) {
        if(n < 4) return n-1;
        int res = 1;
        while(n > 2){
            res *= 3;
            n -= 3;
        }
        if(n == 0) return res;
        if(n == 1) return (res / 3 ) * 4;
        if(n == 2) return res * 2;
    }








评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值