Leetcode Sum问题

1. Two sum

Question:
Given an array of integers, return indices of the two numbers such that they add up to a specific target.

You may assume that each input would have exactly one solution, and you may not use the same element twice.

Example:

Given nums = [2, 7, 11, 15], target = 9,

Because nums[0] + nums[1] = 2 + 7 = 9,
return [0, 1].

Answers

思路:

  • // 创建hashmap
  • // 遍历保存数据到hashmap
  • // 寻找 target-nums[i]是否在hashmap中

写代码注意的地方:

  • HashMap 的泛型为两个变量;
  • 熟悉HashMap的方法 ,put, get,contains, containsKey
  • 注意hashmap的地址冲突问题 需要检验 map.get(complement)!=i
  • 最后需要return一个变量,或者throw 一个错误(java)

Approach 1: Brute Force
The brute force approach is simple. Loop through each element xx and find if there is another value that equals to target - x.

扫描二维码关注公众号,回复: 9005195 查看本文章
class solution{
	public int[] twoSum(int[] nums, int target) {
    for (int i = 0; i < nums.length; i++) {
        for (int j = i + 1; j < nums.length; j++) {
            if (nums[j] == target - nums[i]) {
                return new int[] { i, j };
            }
        }
    }
    throw new IllegalArgumentException("No two sum solution");
	}
}

Complexity Analysis

  • Time complexity : O(n2). For each element, we try to find its
    complement by looping through the rest of array which takes O(n)time.
    Therefore, the time complexity is O(n2)
  • Space complexity : O(1)

Approach 2: Two-pass Hash Table

We reduce the look up time from O(n) to O(1)by trading space for speed. A hash table is built exactly for this purpose, it supports fast look up in near constant time. I say “near” because if a collision occurred, a look up could degenerate to O(n) time. But look up in hash table should be amortized O(1) time as long as the hash function was chosen carefully.

为了加快计算时间,我们需要用空间换时间,寻找一个O(n),O(1)转换的算法。Hash Table 十分的符合。

class Solution {
   public int[] twoSum(int[] nums, int target) {
       Map<Integer, Integer> map = new HashMap<> ();
       for(int i=0; i<nums.length;i++){
           map.put(nums[i],i);
       }
       
       for(int i=0; i<nums.length;i++){
          int complement = target - nums[i];
           if(map.containsKey(complement)&&map.get(complement)!=i){
               return new int[]{i,map.get(complement)};
           }
       }
       throw new IllegalArgumentException("no solution");
   }
}

Approach 3: One-pass Hash Table
It turns out we can do it in one-pass. While we iterate and inserting elements into the table, we also look back to check if current element’s complement already exists in the table. If it exists, we have found a solution and return immediately.

class Solution {
   public int[] twoSum(int[] nums, int target) {
       Map<Integer, Integer> map = new HashMap<> ();
       for(int i=0; i<nums.length;i++){
           int complement = target - nums[i];
           if(map.containsKey(complement)){
               return new int[]{map.get(complement),i};
           }
            map.put(nums[i],i);  
       }
       throw new IllegalArgumentException("no solution");
   }
}

2. Add Two Numbers

Question
You are given two non-empty linked lists representing two non-negative integers. The digits are stored in reverse order and each of their nodes contain a single digit. Add the two numbers and return it as a linked list.

You may assume the two numbers do not contain any leading zero, except the number 0 itself.

Example:

Input: (2 -> 4 -> 3) + (5 -> 6 -> 4)
Output: 7 -> 0 -> 8
Explanation: 342 + 465 = 807.

Answers
在这里插入图片描述
算法思路:按照计算的规则

  1. 建立p,q等于l1,l2, result 初始值为0; 初始化curr =result ; 初始化 carry=0 进位;
  2. 遍历l1,l2直至结束末尾(不为null);
  3. 设x,y等于p,q的val,若为null, 设为0;
  4. 定义sum = x+y+carry;
  5. 下一个carry = sum/10;
  6. curr的当前val 为sum%10;
  7. 更新curr的位置为curr.next; 更新p,q(若不为null)
  8. 循环结束后,检查 carry==1? 如果是,建立新节点等于carry。即最大一位;
  9. 返回result.next;
class Solution{
	public ListNode addTwoNumbers(ListNode l1, ListNode l2){
		//1. 建立p,q等于l1,l2, result 初始值为0; 初始化curr =result ; 初始化 carry=0 进位;
		ListNode result = new ListNode(0);
		ListNode p=l1, q=l2, curr =result;
		int carru =0;	
		
	//2. 遍历l1,l2直至结束末尾(不为null);
		while(p!=null||q!=null){
		
			//3. 设x,y等于p,q的val,若为null, 设为0;
			int  x = (p!=null)?p.val:0;
			int  y = (q!=null)?q.val:0;
			//4. 定义sum = x+y+carry;
			int sum = x+y +carry;
			//5. 下一个carry = sum/10; 
			carry = sum/10;
			//6. curr的当前val 为sum%10; 
			curr.next = new ListNode(sum%10);
			//7. 更新curr的位置为curr.next; 更新p,q(若不为null)
			curr = curr.next;
			if(p!=null) p = p.next;
			if(q!=null) q = q.next;
			
		}
	//8. 循环结束后,检查 carry==1? 如果是,建立新节点等于carry。即最大一位;
	if(carry>0) curr.next= new ListNode(carry);
	//9. 返回result.next;
	return result.next;
	}
}

15. 3Sum

Question
Given an array nums of n integers, are there elements a, b, c in nums such that a + b + c = 0? Find all unique triplets in the array which gives the sum of zero.

Note:

The solution set must not contain duplicate triplets.

Example:

Given array nums = [-1, 0, 1, 2, -1, -4],

A solution set is:
[
[-1, 0, 1],
[-1, -1, 2]
]

Answers:

第一种办法: HashMap
算法思路:

  1. 先排序,后面删除重复的数据; 用HashMap 把数据存一遍;
  2. 遍历数据nums,索引为i,再遍历索引i之后的数据j=i+1; 在HashMap 中查找是否存在key = target = -nums[i]-nums[j], 并且满足条件hashMap(key) 不等于i,不等于j, target>=nums[j];
  3. 如果存在且满足3中条件,设List = [nums[i],nums[j],target]; 用HashSet记录每个List,删除重复List;
class Solution {
   public List<List<Integer>> threeSum(int[] nums) {
        Map<Integer, Integer> hashMap = new HashMap<> ();
        Set<List<Integer>>    hashSet = new HashSet<> ();
        List<List<Integer>>   ans = new ArrayList<> ();
       
       Arrays.sort(nums);
       
       for(int i=0;i<nums.length;i++){
           hashMap.put(nums[i],i);
       }
       
       for(int i=0;i<nums.length;i++){
           for(int j=i+1; j<nums.length;j++){
               int target = -(nums[i]+nums[j]);
               
               if(hashMap.containsKey(target)){
                   int val = hashMap.get(target);
                   if(val!=i&&val!=j&&target>=nums[j]){
                        List tl = Arrays.asList(nums[i],nums[j],target);
                        if(!hashSet.contains(tl)){
                           hashSet.add(tl);
                           ans.add(tl);
                       }
                   }   
               }
           }
       }
       return ans;
    }
}

第二种办法:首尾指针搜索

算法思想:
1.先排序后,遍历nums, 索引为i,得到要寻找的数target = -nums[i];
2.如果nums[i]=nums[i-1] 则continue 跳出这次循环,避免重复;
3.从索引i之后的数组中,while(low<high)用首尾两指针来,搜索其之和与target比较,
即 low = i+1; high = nums.length-1;
4. if target = nums[low]+nums[high]
{ans.add[nums[i],nums[low],nums[high]]
low++,high–;
if(low<high&& nums[low]==nums[low-1]) low++;
if(low<high&& nums[high]==nums[high+1]) high–;}
5. else if target > nums[low]+nums[high]{low ++}
6. else high–

class Solution {
   public List<List<Integer>> threeSum(int[] nums) {
       List<List<Integer>> ans = new ArrayList<> ();
       Arrays.sort(nums);
       for(int i=0; i+2<nums.length;i++){
           if(i>0&&nums[i]==nums[i-1]) continue;
           
           int low =i+1, high = nums.length-1;
           int target = -nums[i];
           while(low<high){
               if (target==nums[low]+nums[high]){
                   ans.add(Arrays.asList(nums[i],nums[low],nums[high]));
                   low++;
                   high--;
                   while(low<high&&nums[low]==nums[low-1]) low++;
                   while(low<high&&nums[high]==nums[high+1]) high--;
               }
               else if (target>nums[low]+nums[high]) low++;
               else high--;
           }
       }
       return ans;
   }
}

16. 3Sum Closest

Question:
Given an array nums of n integers and an integer target, find three integers in nums such that the sum is closest to target. Return the sum of the three integers. You may assume that each input would have exactly one solution.

Example:

Given array nums = [-1, 2, 1, -4], and target = 1.

The sum that is closest to the target is 2. (-1 + 2 + 1 = 2).

Answers:

算法思路:

  1. 先遍历数组,遍历数组nums
  2. 用首尾指针搜索, 得到diff= nums 三个数之和与 target的差值
  3. 根据diff的正负, 更新首尾指针,最小值,用flag 记录flag的正负;
class Solution {
    public int threeSumClosest(int[] nums, int target) {
       List<List<Integer>> ans = new ArrayList<> ();
       Arrays.sort(nums);
       
       //记录三者之和与target的差的绝对值
       int min = 9999;
       //记录diff的正负
       int flag = 1;
       for(int i=0; i+2<nums.length;i++){
           int low =i+1, high = nums.length-1;
           while(low<high){
               int diff = nums[i]+nums[low]+nums[high]-target;
               if (diff==0) return target;
               if (diff>0){
                   high--;
                   if (diff<min){
                      min=diff;
                      flag = 1; 
                   } }    
               if (diff<0){
                   low++;
                   if(-diff<min){
                       min =-diff;
                       flag = -1;
                   }} 
               }
        }
    return target+flag*(min);     
    }
}

18. 4Sum

Question:
Given an array nums of n integers and an integer target, are there elements a, b, c, and d in nums such that a + b + c + d = target? Find all unique quadruplets in the array which gives the sum of target.

Note:

The solution set must not contain duplicate quadruplets.

Example:

Given array nums = [1, 0, -1, 0, -2, 2], and target = 0.

A solution set is:
[
[-1, 0, 0, 1],
[-2, -1, 1, 2],
[-2, 0, 0, 2]
]

Answers:

算法思路:
基本和3sum一样

class Solution {
    public List<List<Integer>> fourSum(int[] nums, int target) {
        List<List<Integer>> ans = new ArrayList<> ();
       Arrays.sort(nums);
        
       for(int i=0; i+3<nums.length;i++){
           if(i>0&&nums[i]==nums[i-1]) continue;
           //first candidate too large, search finished
           if(nums[i]+nums[i+1]+nums[i+2]+nums[i+3]>target)break;
           //first candidate too small
           if(nums[i]+nums[nums.length-1]+nums[nums.length-2]+nums[nums.length-3]<target)continue; 
           
           for(int j=i+1; j+2<nums.length;j++){
          	   //这里需要注意j>i+1
               if(j>i+1&&nums[j]==nums[j-1]) continue;
               //second candidate too large
               if(nums[i]+nums[j]+nums[j+1]+nums[j+2]>target)break;
               //second candidate too small
               if(nums[i]+nums[j]+nums[nums.length-1]+nums[nums.length-2]<target) continue; 
              
               int low =j+1, high = nums.length-1;
               int temp_target = target-nums[i]-nums[j];
               
               while(low<high){
                   if (temp_target==nums[low]+nums[high]){
                       ans.add(Arrays.asList(nums[i],nums[j],nums[low],nums[high]));
                       low++;
                       high--;
                       while(low<high&&nums[low]==nums[low-1]) low++;
                       while(low<high&&nums[high]==nums[high+1]) high--;
                   }
                   else if (temp_target>nums[low]+nums[high]) low++;
                   else high--;
               }
       }
       
     }
        return ans;
    }
}
发布了12 篇原创文章 · 获赞 0 · 访问量 899

猜你喜欢

转载自blog.csdn.net/EPFL_Panda/article/details/100675568
今日推荐