Leetcode Part.2

Leetcode Part.2

前言

刷Leetcode的第二部分 链表部分没有用go写 感觉有点鸡肋

11. Container With Most Water

经典贪心算法 左右两边两开花,从左右往中间遍历

// 24ms

class Solution {
public:
    int maxArea(vector<int>& height) {
        if(height.size() < 2) return 0;
        int left = 0;
        int right = height.size() - 1;
        int area = 0;
        int maxArea = 0;
        while(left < right)
        {
            area = (height[left] < height[right] ? height[left] : height[right]) * (right - left);
            maxArea = area > maxArea ? area : maxArea;
            if(height[left] > height[right])
            {
                right--;
            }
            else
            {
                left++;
            }
        }
        return maxArea;
    }
};
//12ms
func maxArea(height []int) int {
    if len(height) < 2{
        return 0
    }
    left, right := 0, len(height) - 1
    area ,maxArea := 0, 0
    for(left < right){
        if height[left] < height[right]{
            area = height[left] * (right - left)
        } else {
            area = height[right] * (right - left)
        }
        if area > maxArea{
            maxArea = area
        } 
        if(height[left] > height[right]){
            right--
        } else {
            left++
        }
    }
    return maxArea;
}

12. Integer to Roman

由整数转成罗马数字 类似于int to char 大概思路是从最大的位数开始分离原int数字中的内容,并同时在char中加入对应罗马文字

// 16ms
class Solution {
public:
    string intToRoman(int num) {
        string res = "";
        vector<int> value{1000,900,500,400,100,90,50,40,10,9,5,4,1};
        vector<string> symbol{"M","CM","D","CD","C","XC","L","XL","X","IX","V","IV","I"};
        for(int i = 0; i < value.size(); i++)
        {
            while(num >= value[i])
            {
                res += symbol[i];
                num -= value[i];
            }
        }
        return res;
    }
};

突然get到了go的坏处 go的map是无序的 所有需要筛选才可以遍历
筛选map的效率还不如两个切片效率高

//8ms-20ms
import (
    "sort"
)

func intToRoman(num int) string {
	mapper := map[int]string{1000: "M", 900: "CM", 500: "D", 400: "CD", 100: "C", 90: "XC", 50: "L", 40: "XL", 10: "X", 9: "IX", 5: "V", 4: "IV", 1: "I"}
	var keys []int
    for k := range mapper {
        keys = append(keys, k)
    }
	sort.Ints(keys)
	
	var ret string
	for i := 12; i>=0; i-- {
		for num >= keys[i] {
			ret += mapper[keys[i]]
			num -= keys[i]
		}
	}
    return ret
}

//0-12ms avg.8ms
func intToRoman(num int) string {
	keys := []int{1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1}
    values := []string{"M","CM","D","CD","C","XC","L","XL","X","IX","V","IV","I"}

	var ret string
	for i := range keys {
		for num >= keys[i] {
			ret += values[i]
			num -= keys[i]
		}
	}
	return ret
}

15. 3Sum

还记得2Sum吗,这道题可以看成先选定一个数字,再按照2Sum找后面两个值,但是这样会因为map的映射而少很多的结果,同时如果按照左右指针单纯寻找时会导致结果出现重复值,所以需要对重复值进行去除,同时,为了加快程序,应该先分析逻辑,进行合理的剪枝,在这里,减去了最小的数字大于0,最大的数字小于0的分支

// 72ms
class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
        sort(nums.begin(), nums.end());
        vector<vector<int>> res;
        if(nums.empty() || nums.front() > 0 || nums.back() < 0) return {};
        for(int k = 0; k < (int)nums.size() - 2; k++)
        {
            if(nums[k] > 0) break;
            if(k > 0 && nums[k - 1] == nums[k]) continue;
            int target = 0 - nums[k];
            int i = k + 1;
            int j = (int)nums.size() - 1;
            while(i < j)
            {
                if(nums[i] + nums[j] == target)
                {
                    res.push_back({nums[k], nums[i], nums[j]});
                    while(i < j && nums[i] == nums[i + 1]) i++;
                    while(i < j && nums[j] == nums[j - 1]) j--;
                    i++;
                    j--;
                }
                else if(nums[i] + nums[j] < target)
                {
                    i++;
                }
                else
                {
                    j--;
                }
            }
        }
        return res;
    }
};
//28ms
import (
	"sort"
)

func threeSum(nums []int) [][]int {
	if nums == nil || len(nums) < 3 {
		return nil
	}
	sort.Ints(nums)

	ans := [][]int{}
	for i := 0; i < len(nums)-2; i++ {
		if nums[i] > 0 {
			break
		}
		if i > 0 && nums[i] == nums[i-1] {
			continue
		}
		j := i + 1
		k := len(nums) - 1
		for j < k {
			sum := nums[i] + nums[j] + nums[k]
			if sum == 0 {
				ans = append(ans, []int{nums[i], nums[j], nums[k]})
				for j < k && nums[j] == nums[j+1] {
					j++
				}
				for j < k && nums[k] == nums[k-1] {
					k--
				}
				j++
				k--
			} else if sum > 0 {
				k--
			} else {
				j++
			}
		}
	}
	return ans
}

16. 3Sum Closest

这道题与上一题类似,但是需要加上绝对值逼近的思想
class Solution {
public:
    int threeSumClosest(vector<int>& nums, int target) {
        sort(nums.begin(), nums.end());
        int closest = nums[0] + nums[1] + nums[2];
        int diff = abs(target - closest);
        for(int k = 0; k < nums.size() - 2; k++)
        {
            int left = k + 1;
            int right = nums.size() - 1;
            while(left < right)
            {
                int temp = nums[k] + nums[left] + nums[right];
                int newDiff = abs(temp - target);
                if(newDiff < diff)
                {
                    closest = temp;
                    diff = newDiff;
                }
                if(temp > target)
                {
                    right--;
                }
                else if(temp < target)
                {
                    left++;
                }
                else
                {
                    return closest;
                }
            }
        }
        return closest;
    }
};

看了下别人写的 感觉不如我这个好用 我这个可以稳定4ms

//4ms
import (
	"math"
	"sort"
)

func threeSumClosest(nums []int, target int) int {
	for len(nums) < 3 || nums == nil {
		return 0
	}
	sort.Ints(nums)
	closest := nums[0] + nums[1] + nums[2]
	for i := range nums {
		j := i + 1
		k := len(nums) - 1
		for j < k {
			sum := nums[i] + nums[j] + nums[k]
			if sum == target {
				return sum
			}
			closestdiff := math.Abs(float64(closest - target))
			nowdiff := math.Abs(float64(sum - target))

			if nowdiff < closestdiff {
				closest = sum
			}
			if sum < target {
				j++
			}
			if sum > target {
				k--
			}
		}
	}
	return closest
}

17. Letter Combinations of a Phone Number

// 12ms 特别慢的速度
class Solution {
public:
    vector<string> letterCombinations(string digits) {
        if(digits.empty()) return {};
        vector<string> res;
        vector<vector<string>> intermidiary{ {}, {}, {"a", "b", "c"}, {"d", "e", "f"}, {"g", "h", "i"}, {"j", "k", "l"}, {"m", "n", "o"}, {"p", "q", "r", "s"}, {"t", "u", "v"}, {"w", "x", "y", "z"} };
        vector<vector<string>> v;
        for(int i = 0; i < digits.size(); i++)
        {
            v.push_back(intermidiary[digits[i] - '0']);
        }
        DFS_searchres(v, res, 0, digits.length(), "");
        return res;
    }
    void DFS_searchres(vector<vector<string>> v, vector<string>& res, int level, int length, string out)
    {
        if(level == length)
        {
            res.push_back(out);
            return;
        }
        vector<string> s = v[level];
        for(int i = 0; i < s.size(); i++)
        {
            DFS_searchres(v, res, level + 1, length, out + s[i]);
        }
    }
};

学到了学到了。。。。

//0ms
func letterCombinations(digits string) []string {
	table := []string{"", "", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"}
	ret := []string{}
	if len(digits) > 0 {
		help(&ret, digits, "", 0, table)
	}
	return ret
}

func help(ret *[]string, digits string, cur string, index int, table []string) {
	if index == len(digits) {
		*ret = append(*ret, cur)
		return
	}
	tmp := table[digits[index]-48] //ascii to bumber
	for _, t := range tmp {
		help(ret, digits, cur+string(t), index+1, table)
	}
}

18. 4Sum

// 68ms 这道题类似前面几道题的思路,不过就是多套了一层循环,同时也需要合理剪枝
class Solution {
public:
    vector<vector<int>> fourSum(vector<int>& nums, int target) {
        if(nums.size() < 4) return {};
        sort(nums.begin(), nums.end());
        vector<vector<int>> res;
        for(int i = 0; i < nums.size() - 3; i++)
        {
            int t = target - nums[i];
            if(i > 0 && nums[i] == nums[i - 1]) continue;
            for(int j = i + 1; j < nums.size() - 2; j++)
            {
                if(t < 0 && nums[j] > 0) break;
                if(t > 0 && nums[nums.size() - 1] < 0) return res;
                if(j > i + 1 && nums[j] == nums[j - 1]) continue;
                int left = j + 1;
                int right = nums.size() - 1;
                while(left < right)
                {
                    if(nums[j] + nums[left] + nums[right] == t)
                    {
                        res.push_back({nums[i], nums[j], 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(nums[j] + nums[left] + nums[right] < t)
                    {
                        left++;
                    }
                    else
                    {
                        right--;
                    }
                }
            }
        }
        return res;
    }
};

自己的逻辑能力太差了 写了估计几个小时 还缺胳膊少腿的。。。

//8ms
import (
	"sort"
)

func fourSum(nums []int, target int) [][]int {
	if nums == nil || len(nums) < 4 {
		return nil
	}
	sort.Ints(nums)
	ret := [][]int{}
	for i := 0; i < len(nums)-3; i++ {
		newtarget := target - nums[i]
		if i > 0 && nums[i] == nums[i-1] {
			continue
		}
		for j := i + 1; j < len(nums)-2; j++ {
			if newtarget < 0 && nums[j] > 0 {
				break
			}
            if newtarget > 0 && nums[len(nums)-1] < 0 {
				return ret
			}
			if j > i+1 && nums[j] == nums[j-1] {
				continue
			}
			k := j + 1
			l := len(nums) - 1
			for k < l {
				allsum := nums[i] + nums[j] + nums[k] + nums[l]
				sum := nums[j] + nums[k] + nums[l]
				if allsum == target {
					ans := []int{nums[i], nums[j], nums[k], nums[l]}
					ret = append(ret, ans)
					for k < l && nums[k] == nums[k+1] {
						k++
					}
					for k < l && nums[l] == nums[l-1] {
						l--
					}

					k++
					l--
				} else if sum >= newtarget {
					l--
				} else {
					k++
				}
			}
		}

	}
	return ret
}

35. Search Insert Position

Easy easy ```cpp // 8ms class Solution { public:
int searchInsert(vector<int>& nums, int target) {
    if(nums.size() < 1) return 0;
    int res = 0;
    while(res < nums.size() && nums[res] < target)
    {
        res++;
    }
    return res;
} }; ``` 快乐排序。。。 ```go //4ms import (
"sort" )

func searchInsert(nums []int, target int) int { nums = append(nums,target) sort.Ints(nums) for i,v := range nums{ if v == target{ return i } } return 0 }

试了一下另一种写法 发现无论是速度还是内存 没有任何的提升
```go
//4ms
func searchInsert(nums []int, target int) int {
	if len(nums) < 1 {
		return 0
	}
	var i int
	for i < len(nums) && nums[i] < target {
		i++
	}
	return i
}

53. Maximum Subarray

// 16ms 解法一O(n)
class Solution {
public:
    int maxSubArray(vector<int>& nums) {
        int res = INT_MIN;
        int Curmax = 0;
        for(int num: nums)
        {
            Curmax = std::max(Curmax + num, num);
            res = std::max(Curmax, res);
        }
        return res;
    }
};

// 28ms 解法二 分治 不见得就加快了...
class Solution {
public:
    int maxSubArray(vector<int>& nums) {
        if(nums.empty()) return 0;
        return find_max(nums, 0, (int)nums.size() - 1);
    }
    
    int find_max(vector<int>& nums, int left, int right)
    {
        if(left >= right) return nums[left];
        int mid = left + (right - left) / 2;
        int lmax = find_max(nums, left, mid - 1);
        int rmax = find_max(nums, mid + 1, right);
        int mmax = nums[mid];
        int t = mmax;
        for(int i = mid - 1; i >= left; i--)
        {
            t += nums[i];
            mmax = max(mmax, t);
        }
        t = mmax;
        for(int i = mid + 1; i <= right; i++)
        {
            t += nums[i];
            mmax = max(mmax, t);
        }
        return max(mmax, max(lmax, rmax));
    }
};

朴素的解法

//4ms
func maxSubArray(nums []int) int {
	max := math.MinInt32
	tmp := 0
	for _, v := range nums {
		if tmp > 0 {
			tmp += v
		} else {
			tmp = v
		}
		if max < tmp {
			max = tmp
		}
	}
	return max
}

用了分治似乎也没什么提升

//4ms
func maxPart(nums []int, left int, right int) int {
	if left == right {
		return nums[left]
	}
	if left > right {
		return math.MinInt32
	}
	mid := (left + right) >> 1 //右移一位相当于除以二
	maxLeft := maxPart(nums, left, mid-1)
	maxRight := maxPart(nums, mid+1, right)
	partLeftMax := 0
	partRightMax := 0
	sum := 0
	for i := mid - 1; i >= left; i-- {
		sum += nums[i]
		if sum > partLeftMax {
			partLeftMax = sum
		}
	}
	sum = 0
	for i := mid + 1; i <= right; i++ {
		sum += nums[i]
		if sum > partRightMax {
			partRightMax = sum
		}
	}
	partMidMax := partLeftMax + partRightMax + nums[mid]
	tmp := 0
	if maxLeft > maxRight {
		tmp = maxLeft
	} else {
		tmp = maxRight
	}
	if tmp < partMidMax {
		tmp = partMidMax
	}
	return tmp
}

func maxSubArray(nums []int) int {
	return maxPart(nums, 0, len(nums)-1)
}

67. Add Binary

 这道题类似于前面做过的那道链表加法的题
//	8 ms
class Solution {
public:
    string addBinary(string a, string b) {
        if(a.empty()) return b;
        if(b.empty()) return a;
        int length_a = a.length() - 1;
        int length_b = b.length() - 1;
        string res = "";
        int flag = 0;
        while(length_a >= 0 || length_b >= 0)
        {
            int var_1 = length_a >= 0 ? (a[length_a] - '0') : 0;
            int var_2 = length_b >= 0 ? (b[length_b] - '0') : 0;
            int t = var_1 + var_2 + flag;
            flag = t / 2;
            t = t % 2;
            res = to_string(t) + res;
            if(length_a >= 0) length_a--;
            if(length_b >= 0) length_b--;
        }
        if(flag) res = "1" + res;
        return res;
    }
};

70. Climbing Stairs

经典爬梯子题
// 0ms 不出所料,用递归直接当场螺旋爆炸了,这个方法我是真的忘记了,勉强算是dp的(其实算不上)
class Solution {
public:
    int climbStairs(int n) {
        if (n <= 1) return 1;
        vector<int> dp(n);
        dp[0] = 1;
        dp[1] = 2;
        for(int i = 2; i < n; i++)
        {
            dp[i] = dp[i - 1] + dp[i - 2];
        }
        return dp[n - 1];
    }
};

没搞懂原理。。。放在这膜拜吧。。。

//0ms 1.9mb all 100%
func climbStairs(n int) int {
	a, b := 1, 1
	n--
	for n > 0 {
		n--
		b = b + a
		a = b - a
	}
	return b
}

83. Remove Duplicates from Sorted List

Easy ```cpp // 16ms class Solution { public:
ListNode* deleteDuplicates(ListNode* head) {
    ListNode* curPoint = head;
    while(curPoint && curPoint->next)
    {
        while(curPoint->next  && curPoint->val == curPoint->next->val)
        {
            ListNode* p = curPoint->next;
            curPoint->next = curPoint->next->next;
            delete p;
        }
        curPoint = curPoint->next;
    }
    return head;
} }; ``` ```go

## 100. Same Tree
    看到树直接递归就完事了
```cpp
// 0ms
class Solution {
public:
    bool isSameTree(TreeNode* p, TreeNode* q) {
        if(!p && !q) return true;
        if((p && !q) || (!p && q) || (p->val != q->val)) return false;
        return isSameTree(p->left, q->left) && isSameTree(p->right, q->right);
    }
};

101. Symmetric Tree

这道题还是树,自然而然想到递归,但是这道题要注意的是树的左右两边要对称,所以遍历的时候应该注意左右子树分开同时遍历 ```cpp // 0ms class Solution { public:
bool isSymmetric(TreeNode* root) {
    if(!root) return true;
    return isSymmetric(root->left, root->right);
}
bool isSymmetric(TreeNode* left, TreeNode* right)
{
    if(!left && !right) return true;
    if(left && !right || right && !left || right->val != left->val) return false;
    return isSymmetric(left->right, right->left) && isSymmetric(left->left, right->right);
} }; ```

104. Maximum Depth of Binary Tree

Easy 看到树还是递归就行,注意使用递归对深度进行保存 ```cpp class Solution { public:
int maxDepth(TreeNode* root) {
    if(!root) return 0;
    return max(curDepth(root->left, 1), curDepth(root->right, 1));
}
int curDepth(TreeNode* node, int depth)
{
    if(!node) return depth;
    depth++;
    return max(curDepth(node->left, depth), curDepth(node->right, depth));
} }; ```

107. Binary Tree Level Order Traversal II

看到树递归就完事了,不过我这个速度实在是垃圾 ```cpp // 8ms class Solution { public:
vector<vector<int>> levelOrderBottom(TreeNode* root) {
    if(!root) return {};
    vector<vector<int>> res;
    foreach_tree(res, root, 0);
    return vector<vector<int>> (res.rbegin(), res.rend());
}
void foreach_tree(vector<vector<int>>& res, TreeNode* node, int depth)
{
    if(!node) return;
    if(res.size() == depth) res.push_back({});
    if(node->left) foreach_tree(res, node->left, depth + 1);
    if(node->right) foreach_tree(res, node->right, depth + 1);
    res[depth].push_back(node->val);
} }; ```

108. Convert Sorted Array to Binary Search Tree

把一个数组变成二叉排序树
这道题如果以前没有接触过二分法之类的还是挺难的,因为它要求要左右子树度差不大于1,就得用二叉法来做 ```cpp // 24ms class Solution { public:
TreeNode* sortedArrayToBST(vector<int>& nums) {
    if(nums.empty()) return nullptr;
    int mid = nums.size() / 2;
    TreeNode* cur = new TreeNode(nums[mid]);
    vector<int> left(nums.begin(),nums.begin() + mid);
    vector<int> right(nums.begin() + mid + 1, nums.end());
    cur->left = sortedArrayToBST(left);
    cur->right = sortedArrayToBST(right);
    return cur;
} }; ```

© 2021. All rights reserved.

本站总访问量 Web Analytics

Powered by Hydejack v9.1.2 & Moded by ZYA