leetcode--Valid Triangle Number

问题描述:给定一个非负数组,将它们的大小作为长度,能够在组成多少个合法的三角形。下面是一个例子:

Input: [2,2,3,4]
Output: 3
Explanation:
Valid combinations are: 
2,3,4 (using the first 2)
2,3,4 (using the second 2)
2,2,3

分析:
(1)这个问题我开始没有想到较好的方法,于是就从基本的算法开始着手看看会不会有什么改进。很明显暴力破解法一共有Cn3C_n^3Cn3中情况,O(n3)O(n^3)O(n3)的时间复杂度。

(2)对于判断三角形是否合法,就是两边之和大于第三边而已。如果三条边的大小排列关系,就是两个较小边之和大于最大边。我们想要改进这个算法,就是看看有没有多余的步骤可以省去。

(3)很明显,假如xi&lt;=xj&lt;=xpx_i&lt;=x_j&lt;=x_pxi<=xj<=xp,这三条边如果不能组成三角形,对于xm&gt;=xpx_m&gt;=x_pxm>=xp,与xix_ixixjx_jxj的组合也没有必要尝试了。

但是这种依赖大小关系的改进方法需要排序,考虑到排序算法是O(nlogn)O(nlogn)O(nlogn)的复杂度,小于原来的算法,所以是可以接受的。因此写了第一版代码:

class Solution {
    public int triangleNumber(int[] nums) {
    	Arrays.sort(nums);
		int rs = 0;
		for(int i = 0;i<nums.length-2;i++)
			for(int j=i+1;j<nums.length-1;j++) 
				for(int p=j+1+counter;p<nums.length;p++) {
					if(nums[p]-nums[j]>=nums[i])break;
						rs++;
				}
        return rs;
    }
}

这个时间复杂度比原来O(n3)O(n^3)O(n3)好一些,但是总觉得还有哪里可以改进。对于一次遍历中的xi&lt;=xj&lt;=xpx_i&lt;=x_j&lt;=x_pxi<=xj<=xp,假如这三个数字符合要求,即
xi+xj&gt;xpx_i+x_j&gt;x_pxi+xj>xp,同时存在xi+xj&lt;xp+1x_i+x_j&lt;x_{p+1}xi+xj<xp+1,那么对于任意的j+1&lt;m&lt;=pj+1&lt;m&lt;=pj+1<m<=p
xi+xm&gt;xpx_i+x_m&gt;x_pxi+xm>xp必然也是成立的,只需要从p+1的地方开始检验即可。举一个例子说明
假如排序后的数组如下:

6,8,10,11,12,13,14,15,196,8,10,11,12,13,14,15,196,8,10,11,12,13,14,15,19
如果我们在外层循环中已经挑选的较小的数字是6,8,那么验证最大数字只能是10,11,12,13这四种可能
那么下一轮循环挑选的较小数字是6,10, 这时11,12,13这三个数字其实不需再验证了,应该从14开始验证。

所以有了下面的算法

class Solution {
    public int triangleNumber(int[] nums) {
        Arrays.sort(nums);
		int temp = 0,counter = 0;
		int rs = 0;
		for(int i = 0;i<nums.length-2;i++) {
			for(int j=i+1;j<nums.length-1;j++) {
				temp=0;
				for(int p=j+1+counter;p<nums.length;p++) {
					if(nums[p]-nums[j]>=nums[i])break;
					else temp++;
				}
				rs +=(temp+counter);
				counter = temp+counter-1>0?temp+counter-1:0;
			}
		}
        return rs;
    }
}

时间复杂度分析:
从内层循环来看,尽管看起来有两层内循环,但是,第三层循环并不是O(n)的规模,而且始终向前,从不回头。在整个第二层循环完成时,其实才遍历了一次数组。我们再次以下面的数组为例,将第二层循环展开看:
6,8,10,11,12,13,14,15,196,8,10,11,12,13,14,15,196,8,10,11,12,13,14,15,19
最外层选定6
\quad次外层选定8
\quad\qquad内层遍历10,11,12,13,14(在14这里停止)
\quad次外层选定10
\quad \quad 内层遍历14,15,19(在19这里停止)
\quad次外层选定11
\quad \quad 内层循环直接跳出。。。
\quad常数时间计算这一轮的结果

所以,其实里面虽然有两个循环,但是时间复杂度却是O(n)O(n)O(n)
因此最终的时间复杂度是O(n2)O(n^2)O(n2)
在这里插入图片描述
这是提交结果,看来还有更好的方案,大神确实多。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值