力扣15三數之和,天佑中華!!!!!!!

給定一個包含 n 個整數的數組 nums,判斷 nums 中是否存在三個元素 a,b,c ,使得 a + b + c = 0 ?找出所有滿足條件且不重複的三元組。
注意:答案中不可以包含重複的三元組。
示例:給定數組 nums = [-1, 0, 1, 2, -1, -4],
滿足要求的三元組集合爲:
[ [-1, 0, 1], [-1, -1, 2] ]
class Solution {
    	 public  List<List<Integer>> threeSum(int[] nums) {
    	 }
    	 }

這道題目很有意思,這裏提供兩種方法:
首先第一種是蠻力法,也是我最先想到的,嗯
這個方法的優點是思維簡單,缺點是時間複雜度高,當輸入數據較多時,難以獲得有效的滿意度。
蠻力法的思路是三次循環計算每三個組合,然後進行計算滿足的三個數,和已在表中的進行對比進行去重,依次做下去。
代碼如下:

	  public static List<List<Integer>> threeSum(int[] nums) {
	  List<List<Integer>> a=new ArrayList<>();
		 int len=nums.length;
		 for(int i=0;i<len-2;i++){
			 for(int j=i+1;j<len-1;j++)
				 for(int k=j+1;k<len;k++){
					 if(nums[i]+nums[j]+nums[k]==0){
						 List<Integer> temp=new ArrayList<>();
						 temp.add(nums[i]);
						 temp.add(nums[j]);
						 temp.add(nums[k]);
						 temp.sort(null);//有序的才能進行比較
						 if(!a.contains(temp)){
							 a.add(temp);					 					 
						 }
					 }
				 }
		 }	
		  return a;      
	   }

第二種是雙指針法,我看了下別人的題解,用自己的語言給大家整理下
我們爲了減輕複雜度,要對數組進行排序
然後呢我們對數組進行遍歷,從小到大依次爲最小值,當最小值都大於0時,必三數之和大於0,所以我們某種意義上就排除了一半的時間複雜度。
接下來就是循環過程中,右指針是最大值開始,左指針爲最小值的前一個開始。當右指針小於等於左指針時我們要進行下一輪循環,同時在本輪循環中,當三數和大於0時,我們將右指針向左移,也就是三數之和變小
當三數之和小於0時,我們將左指針向右移,三數之和也就變大了。
我們減輕複雜度的方法,比蠻力法少了列表去重,因爲我們將數組排好序後,重複的元素通過指針就自動去重了。
代碼如下:

public static List<List<Integer>> threeSum(int[] nums) {
		 List<List<Integer>> a=new ArrayList<>();
		 int len=nums.length;
		  Arrays.sort(nums);//數組排序
		 if(len<3||nums==null)
			 return a;//極限條件,數組爲空或長度小於3時
		 else if(nums[0]<=0&&nums[len-1]>=0){//當最小都大於0,或是最大都小於0,也就無三數之和==0的可能性了。
			 for(int i=0;i<len;i++){//開始循環
				 if(nums[i]>0) break;//最小值大於0時跳出循環
				 if(i>0&&nums[i]==nums[i-1]){
					 continue;//去除最小值的重複元素
				 }//確定左右指針位置
				 int Left=i+1;
				 int Right=len-1;
				 while(Left<Right){
					 int sum=nums[i]+nums[Left]+nums[Right];
					 if(sum==0){
						 a.add(Arrays.asList(nums[i],nums[Left],nums[Right]));
						 while(Left<Right&&nums[Left]==nums[Left+1]) Left++;//去左重
						 while(Left<Right&&nums[Right]==nums[Right-1]) Right--;//去右重
						 Left++;//指針變化
						 Right--;
					 }
					 else if(sum<0)
						 Left++;//和小於0左指針右移,和變大
					 else if(sum>0)
						 Right--;//和大於0 右指針左移,和變小
				 }
			 }
		 }
		 return a;      
	    }

最後宣傳下我個人的微信公衆號,微信搜索:可及的小屋,有志向整副業,娛樂的程序員們,歡迎您的到來。謝謝。
100G程序員資料,自取哦!!
可及的小屋

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章