LeetCode1 C++ Two Sum

LeetCode1 Two Sum C++ 解法总结

  • 题目
  • 暴力遍历法
    • 方式1
    • 方式2
  • 使用map方法
    • 方式1:unordered_map
      • 遍历一遍
      • 换个顺序
      • 改变一下判断方式
      • 利用数组的长度
      • 遍历两遍
    • 方式2:map
    • map和unordered_map
  • 排序
  • Error 整理

题目

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].

有三点需要注意:

1、返回的为两个元素的索引值;
2、假设有且只有一组答案;
3、同一个元素不能使用两次。

暴力遍历法

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).

方式1

class Solution {
     
public:
    vector<int> twoSum(vector<int>& nums, int target) {
     
        vector<int> loc(2);
        for (int i = 0; i < nums.size() - 1; i++) {
     
            for (int j = i + 1; j < nums.size(); j++) {
     
                if (nums[i] + nums[j] == target) {
     
                    loc = {
     i, j};
                    return loc;
                }
            }
        }
        return loc;
    }
};

方式2

class Solution {
     
public:
    vector<int> twoSum(vector<int>& nums, int target) {
     
        int length = nums.size();
        vector<int> ans; //不定长数组
        for (int i = 0; i < length; i++) {
     
            for (int j = 0; j < i; j++) {
     
                if (nums[i] + nums[j] == target) {
     
                    ans.push_back(j);
                    ans.push_back(i);
                    return ans;
                }
            }
        }
        return ans;
    }
};

对不定长数组a的操作

	a.size():获取数组的大小
	a.resize():改变数组的大小
	a.push_back():在数组尾部增添元素
	a.pop_back():删除数组的最后一个元素

使用map方法

unordered_mapmap类似,都是存储 (key, value) 的值,即键值对:可以通过key快速索引到value。不同的是unordered_map不会根据key的大小进行排序,存储时是根据key的hash值判断是否为要寻找的元素

方式1:unordered_map

遍历一遍

Complexity Analysis:
Time complexity: O(n). We traverse the list containing n elements only once. Each look up in the table costs only O(1) time.
Space complexity: O(n). The extra space required depends on the number of items stored in the hash table, which stores at most n elements.

使用unordered_map。遍历数组,若 (target - nums[i]) 的值不在其中,将 (nums[ i ], i) 作为(key, value) 存入map中。否则,返回其对应的索引和当前数组元素的索引。

class Solution {
     
public:
    std::vector<int> twoSum(vector<int>& nums, int target) {
     
    	std::vector<int> res; // 不定长数组
    	std::unordered_map<int, int> hashs; //value->index map
    	for (int i = 0; i < nums.size(); i++) {
     
        	if (hashs.end() != hashs.find(target - nums[i])) 
        	// target-num[i] 在map里
        	{
     
            	res.push_back(hashs[target - nums[i]]);
            	res.push_back(i);
            	return res;
        	}
        	hashs.insert(std::make_pair(nums[i], i));
        	// 使用make_pair
        	// 如果不在,就插入到map中
    	}
    	return res;
    }
};

也可以使用下面的方式来判断返回的两个索引的顺序:

class Solution {
     
public:
    vector<int> twoSum(vector<int>& nums, int target) {
     
        unordered_map<int, int> num_map;
        vector<int> res;
        for (int i = 0; i < nums.size(); i++) {
     
            int tmp = target - nums[i];
            if (num_map.find(tmp) != num_map.end()) {
     
                int beg = i > num_map[tmp] ? num_map[tmp] : i; 
                int end = i > num_map[tmp] ? i : num_map[tmp];
                // beg为两个索引中小的那个
                // end为两个索引中大的那个
                res.push_back(beg);
                res.push_back(end);
                break;
            }
            num_map[nums[i]] = i;
        }
        return res;
    }
};

换个顺序

class Solution {
     
public:
	vector<int> twoSum(vector<int>& nums, int target) {
     
		vector<int> result(2, -1);
		unordered_map<int, int> m;
		for (int i = 0;i < nums.size(); i++)
		{
     
			if (m.end() == m.find(target - nums[i]))
				m.insert(map<int, int>::value_type(nums[i], i));
				// 使用map
			else
			{
     
				result[0] = m[target - nums[i]];
				result[1] = i;
				return result;
			}
		}
        return result;
	}

};

改变一下判断方式

class Solution {
     
public:
	vector<int> twoSum(vector<int>& nums, int target) {
     
		unordered_map<int, int> m;
		vector<int> result(2, -1);
		for (int i = 0;i < nums.size(); i++)
		{
     
			if (!m.count(nums[i]))
				m.insert(pair<int, int>(nums[i], i));
			if (m.count(target - nums[i]))
			{
     
				int t = m[target - nums[i]];
				if (t < i) // 下标不能相同
                {
     
					result[0] = t;
					result[1] = i;
					return result;
                    // nums[i]所指向的下标一定是大于target-nums[i]所对应的下标的
                    // 所以有r[0]和r[1]的先后顺序
				}
			}
		}
        return result;
	}
};

利用数组的长度

class Solution {
     
public:
    vector<int> twoSum(vector<int>& nums, int target) {
     
        // Only really have to search if there's more than 2 elements...
        if(nums.size() > 2){
     
            // So... the known solution is to use a hashmap with the stored differences...
            map<int,int> summer; // 
            for(int i=0;i<nums.size();i++){
     
                int theDiff = target-nums[i];
                if(summer.find(theDiff)==summer.end()){
     
                    summer[nums[i]]=i;
                } else {
     
                    return {
     summer[theDiff],i};
                }
            }
        }
        //If there's only 2 elements, obviously that's the answer then...
        return {
     0,1};
    }
};

遍历两遍

第一个循环:将所有 (key, value) 存入map中;
第二个循环:查找符合题目要求的数组元素,返回其索引值。

Complexity Analysis:
Time complexity: O(n). We traverse the list containing nn elements exactly twice. Since the hash table reduces the look up time to O(1), the time complexity is O(n).
Space complexity: O(n). The extra space required depends on the number of items stored in the hash table, which stores exactly n elements.

class Solution {
     
public:
    vector<int> twoSum(vector<int>& nums, int target) {
     
        unordered_map<int, int> num_map;
        vector<int> res;
        for (int i = 0; i < nums.size(); i++) {
     
            num_map[nums[i]] = i; 
        }
        for (int i = 0; i < nums.size(); i++) {
     
            int tmp = target - nums[i];
            if (num_map.find(tmp) != num_map.end() && num_map[tmp] != i)
            // num_map[tmp] != i的目的是防止同一个元素被用两次
            // e.g. nums: [3,0,8], target: 6
            // 3 + 3 = 6, 但是同一个元素不能使用两次,应该排除这种情况
            {
     
                res.push_back(i);
                res.push_back(num_map[tmp]);
                break;
            }
        }
        return res;
    }
};

方式2:map

时间复杂度:O(log(n))

class Solution {
     
public:
    vector<int> twoSum(vector<int>& nums, int target) {
     
        map<int, int> m;
        vector<int> index;
        for(int i = 0; i < nums.size(); i++)
        {
     
            if(m.count(target - nums[i]) != 0)
            {
     
                index.push_back(m[target - nums[i]]);
                index.push_back(i);
                break;
            }
            m[nums[i]] = i;
        }

        return index;
    }
};

map和unordered_map

链接: 简述C++中map和unordered_map的用法.
链接: c++中map与unordered_map的区别.

排序

需要注意的是sort完数组后原数组的顺序已经被改变,这个时候返回的索引值也出现了变化。

class Solution {
     
public:
    vector<int> twoSum(vector<int>& nums, int target) {
     
        vector<int> a = nums;
        vector<int> m, res;
        sort(a.begin(), a.end()); // 改变a,原数组保持不变
        for (int i = 0; i < a.size(); i++) {
     
            int l = i + 1;
            int h = a.size() - 1;
            int goal = target - a[i];
            while (l <= h) {
     
                if (a[l] == goal) {
     
                    m = {
     a[i], a[l]};
                    break;
                }
                else if (a[h] == goal) {
     
                    m = {
     a[i], a[h]};
                    break;
                }
                else {
     
                    l++;
                    h--;
                }
            }
        }
        for (int i = 0; i < a.size(); i++) {
     
            if (nums[i] == m[0] or nums[i] == m[1])
                res.push_back(i);      
        }
        return res;        
    }
};

Error 整理

1、control reached end of non_void function
一些本应带有返回值的函数到达结尾后可能并没有返回任何值,检查一下每个控制流是否都有返回值。

你可能感兴趣的:(刷题笔记,Leetcode,C++)