算法唯手熟尔5月(主要为leetcode)---希望可以日更

2020/5/1

5/1第一天,半年又要过去了

leetcode 21. 合并两个有序链表_Go

很简单的题目

package main

import "fmt"

// ListNode Struct
type ListNode struct {
	Val  int
	Next *ListNode
}

func mergeTwoLists(l1 *ListNode, l2 *ListNode) *ListNode {
	if l1 == nil && l2 == nil {
		return nil
	}
	if l1 == nil || l2 == nil {
		if l1 == nil {
			return l2
		}
		return l1
	}
	head := &ListNode{}
	tail := head
	for l1 != nil && l2 != nil {
		if l1.Val < l2.Val {
			tail.Next = l1
			l1 = l1.Next
			tail = tail.Next
		} else {
			tail.Next = l2
			l2 = l2.Next
			tail = tail.Next
		}
	}
	if l1 != nil {
		tail.Next = l1
	}
	if l2 != nil {
		tail.Next = l2
	}
	return head.Next
}

func main() {
	l1 := &ListNode{1, nil}
	l1.Next = &ListNode{2, nil}
	l1.Next.Next = &ListNode{4, nil}

	l2 := &ListNode{1, nil}
	l2.Next = &ListNode{3, nil}
	l1.Next.Next = &ListNode{4, nil}

	root := mergeTwoLists(l1, l2)
	fmt.Println(root.Val)
	fmt.Println(root.Next.Val)
}

leetcode 15. 三数之和_C++
#include<stdio.h>
#include<vector>
#include<algorithm>

using namespace std;

vector<vector<int>> threeSum(vector<int>& nums) {
    vector<vector<int>> ans;
    if(nums.size()<3) return ans;
    sort(nums.begin(), nums.end());
    if(nums[0]>0) return ans;
    int i=0;
    while (i<nums.size()){
        if(nums[i]>0) break;
        int left=i+1;
        int right=nums.size()-1;
        while(left<right){
            long long x=nums[i];
            long long y=nums[left];
            long long z=nums[right];
            if(x+y>0-z) right--;
            else if(x+y<0-z) left++;
            else{
                vector<int> temp;
                temp.push_back(nums[i]);
                temp.push_back(nums[left]);
                temp.push_back(nums[right]);
                ans.push_back(temp);
                while(left<right&&nums[left] == nums[left+1]) left++;
                while(left<right&&nums[right] == nums[right-1]) right--;
                left++;
                right--;
            }
        } 
        while(i+1<nums.size()&&nums[i] == nums[i+1]) i++;
        i++;
    }
    return ans;
}

int main(){
    vector<int> nums={-1, 0, 1, 2, -1, -4};
    vector<vector<int>> ans=threeSum(nums);
    for(int i=0;i<ans.size();i++){
        for(int j=0;j<ans[i].size();j++){
            printf("%d ",ans[i][j]);
        }
        printf("\n");
    }
    return 0;
}

2020/5/2

leetcode 3. 无重复字符的最长字串_Go
package main

import "fmt"

// 第一反应可以用回溯
// 后来觉得边界太难确定了,就老老实实学习了滑动窗口
func lengthOfLongestSubstring(s string) int {
	ans := 0
	mp := make(map[byte]int, 10)
	if len(s) <= 1 {
		ans = len(s)
		return ans
	}
	currentLen := 0
	startIndex := 0
	for i := 0; i < len(s); i++ {
		_, ok := mp[s[i]]
		if !ok {
			mp[s[i]] = i
			currentLen++
		} else {
			if currentLen > ans {
				ans = currentLen
			}
			startIndex = max(mp[s[i]], startIndex)
			currentLen = i - startIndex
			mp[s[i]] = i
		}
	}
	if currentLen > ans {
		ans = currentLen
	}
	return ans
}

func max(a int, b int) int {
	if a > b {
		return a
	}
	return b
}

func main() {
	s := "abcabcbb"
	fmt.Println(lengthOfLongestSubstring(s))
}

leetcode 16. 最接近的三数之和_C++

这题和昨天的三数之和做法一样,熟悉一下就好

#include<stdio.h>
#include<algorithm>
#include<vector>

using namespace std;

// two pointers
int threeSumClosest(vector<int>& nums, int target) {   
    int ans=0;
    if(nums.size()<3) return ans;
    sort(nums.begin(),nums.end());
    ans=nums[0]+nums[1]+nums[2];
    for(int i=0;i<nums.size();i++){
        int st=i+1,ed=nums.size()-1;
        while(st<ed){
            int sum=nums[st]+nums[ed]+nums[i];
                if(abs(target-sum)<abs(target-ans)) ans = sum;
                if(sum == target) return sum;
                else if(sum < target) st++;
                else ed--;
        }
    }
    return ans;
}

int main(){
    int a[4]={-1,2,1,-4};
    vector<int> nums(a,a+4);
    int ans=threeSumClosest(nums,1);
    printf("%d\n",ans);
    return 0;
}

2020/5/3

leetcode 19. 删除链表的倒数第N个节点_C++
#include<stdio.h>

using namespace std;

struct ListNode {
    int val;
    ListNode *next;
    ListNode(int x) : val(x), next(NULL) {}
};

// 学了一手哑结点和删除
ListNode* removeNthFromEnd(ListNode* head, int n) {
    ListNode* dummy=new ListNode(0);
    dummy->next=head;
    ListNode* first=dummy;
    ListNode* second=dummy;
    for(int i=0;i<=n;i++){
        first=first->next;
    }
    while (first!=nullptr)
    {
        first=first->next;
        second=second->next;
    }
    second->next=second->next->next;
    return dummy->next;
}

int main(){
    ListNode* head=new ListNode(1);
    head->next=new ListNode(2);
    head->next->next=new ListNode(3);
    head->next->next->next=new ListNode(4);
    head->next->next->next->next=new ListNode(5);
    ListNode* ans=removeNthFromEnd(head,2);
    printf("%d\n",ans->val);
    printf("%d\n",ans->next->next->next->val);
    return 0;
}

2020/5/4

leetcode 45. 跳跃游戏 II_Go
package main

import "fmt"

// 之前做过一道类似的跳跃游戏
// 原题是能否跳到尾部
// 现在改成最少跳跃几次
// 第一个反应是dp,但仔细想一下贪心也可以了

// 方法一,从末尾处贪心
func jump1(nums []int) int {
	idx := len(nums) - 1
	steps := 0
	for idx > 0 {
		for i := 0; i < idx; i++ {
			if i+nums[i] >= idx {
				idx = i
				steps++
				break
			}
		}
	}
	return steps
}

// 方法二,正向贪心,和原题差不多
func jump(nums []int) int {
	n := len(nums)
	steps := 0
	maxIdx := 0
	end := 0
	for i := 0; i < n-1; i++ {
		maxIdx = max(maxIdx, i+nums[i])
		if i == end {
			end = maxIdx
			steps++
		}
	}
	return steps
}

func max(x, y int) int {
	if x > y {
		return x
	}
	return y
}

func main() {
	nums := []int{2, 3, 1, 1, 4}
	fmt.Println(jump(nums))
}

2020/5/5

leetcode 98. 验证二叉搜索树_Go
package main

import (
	"fmt"
	"math"
)

// TreeNode struct
type TreeNode struct {
	Val   int
	Left  *TreeNode
	Right *TreeNode
}

// 挺基本的题目,直接递归就好了
func isValidBST(root *TreeNode) bool {
	return recurse(root, math.MinInt64, math.MaxInt64)
}

func recurse(root *TreeNode, lower int, upper int) bool {
	if root == nil {
		return true
	}
	if root.Val <= lower || root.Val >= upper {
		return false
	}
	return recurse(root.Left, lower, root.Val) && recurse(root.Right, root.Val, upper)
}

// 还有很基本的一个思路,就是结合中序遍历即可
// 不通过是因为leetcode中golang全局变量的问题
var pre int = math.MinInt64

func isValidBST2(root *TreeNode) bool {
	if root == nil {
		return true
	}
	// 访问左子树
	if !isValidBST2(root.Left) {
		return false
	}
	// 访问当前节点:如果当前节点小于等于中序遍历的前一个节点,说明不满足BST,返回 false;否则继续遍历。
	if root.Val <= pre {
		return false
	}
	pre = root.Val
	// 访问右子树
	return isValidBST2(root.Right)
}

func main() {
	root := &TreeNode{
		Val:   0,
		Left:  nil,
		Right: nil,
	}
	fmt.Println(isValidBST2(root))
}

2020/5/6

leetcode 983. 最低票价_Go
package main

import "fmt"

// 第一反应就是dp
func mincostTickets(days []int, costs []int) int {
	dp := make([]int, days[len(days)-1]+1)
	idx := 0
	for i := 1; i <= days[len(days)-1]; i++ {
		if i == days[idx] {
			dp[i] = min(dp[max(0, i-1)]+costs[0], dp[max(0, i-7)]+costs[1])
			dp[i] = min(dp[max(0, i-30)]+costs[2], dp[i])
			idx++
		} else {
			dp[i] = dp[i-1]
		}
	}
	return dp[len(dp)-1]
}

func min(a, b int) int {
	if a < b {
		return a
	}
	return b
}

func max(a, b int) int {
	if a > b {
		return a
	}
	return b
}

func main() {
	days := []int{1, 4, 6, 7, 8, 20}
	costs := []int{2, 7, 15}
	fmt.Println(mincostTickets(days, costs))
}

2020/5/7

leetcode 572. 另一个树的子树_Go
package main

import "fmt"

// TreeNode struct
type TreeNode struct {
	Val   int
	Left  *TreeNode
	Right *TreeNode
}

func newNode(val int) *TreeNode {
	return &TreeNode{
		Val:   val,
		Left:  nil,
		Right: nil,
	}
}

func creatTree(a []int) *TreeNode {
	length := len(a)
	if length == 0 {
		return nil
	}
	node := newNode(a[0])
	queue := []*TreeNode{}
	queue = append(queue, node)
	num := 1
	for num < length {
		top := queue[0]
		queue = queue[1:]
		if top.Left == nil {
			if a[num] != -1 {
				top.Left = newNode(a[num])
				queue = append(queue, top.Left)
			}
			num++
		}
		if num == length {
			break
		}
		if top.Right == nil {
			if a[num] != -1 {
				top.Right = newNode(a[num])
				queue = append(queue, top.Right)
			}
			num++
		}
	}
	return node
}

// 最基础的DFS,别的方法我是想不出的
// 自己写的太丑了,可以运行,就贴了官方的,反正DFS都差不多
func isSubtree(s *TreeNode, t *TreeNode) bool {
	if s == nil {
		return false
	}
	return check(s, t) || isSubtree(s.Left, t) || isSubtree(s.Right, t)
}

func check(a, b *TreeNode) bool {
	if a == nil && b == nil {
		return true
	}
	if a == nil || b == nil {
		return false
	}
	if a.Val == b.Val {
		return check(a.Left, b.Left) && check(a.Right, b.Right)
	}
	return false
}

func main() {
	s := []int{3, 4, 5, 1, 2, -1, -1}
	t := []int{4, 1, 2}
	S := creatTree(s)
	T := creatTree(t)
	fmt.Println(isSubtree(S, T))
}

2020/5/9

昨天脑子已经不清楚了,昨天的题目自己稍微写了一下,就挂个题解吧,觉得脑子不清楚的时候,效率确实差

leetcode 211. 最大正方形_C++

bruteforce

#include<stdlib.h>
#include<stdio.h>
#include<vector>
#include<algorithm>

using namespace std;

int maximalSquare(vector<vector<char>>& matrix) {
    if (matrix.size() == 0 || matrix[0].size() == 0) {
        return 0;
    }
    int maxSide = 0;
    int rows = matrix.size(), columns = matrix[0].size();
    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < columns; j++) {
            if (matrix[i][j] == '1') {
                // 遇到一个 1 作为正方形的左上角
                maxSide = max(maxSide, 1);
                // 计算可能的最大正方形边长
                int currentMaxSide = min(rows - i, columns - j);
                for (int k = 1; k < currentMaxSide; k++) {
                    // 判断新增的一行一列是否均为 1
                    bool flag = true;
                    if (matrix[i + k][j + k] == '0') {
                        break;
                    }
                    for (int m = 0; m < k; m++) {
                        if (matrix[i + k][j + m] == '0' || matrix[i + m][j + k] == '0') {
                            flag = false;
                            break;
                        }
                    }
                    if (flag) {
                        maxSide = max(maxSide, k + 1);
                    } else {
                        break;
                    }
                }
            }
        }
    }
    int maxSquare = maxSide * maxSide;
    return maxSquare;
}

int main(){
    return 0;
}

dp

这题还可以dp我是真的没想到,但看了题解之后觉得想到是正常的,还是要多练练

#include<stdlib.h>
#include<stdio.h>
#include<vector>
#include<algorithm>

using namespace std;

int maximalSquare(vector<vector<char>>& matrix) {
    if (matrix.size() == 0 || matrix[0].size() == 0) {
        return 0;
    }
    int maxSide = 0;
    int rows = matrix.size(), columns = matrix[0].size();
    vector<vector<int>> dp(rows, vector<int>(columns));
    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < columns; j++) {
            if (matrix[i][j] == '1') {
                if (i == 0 || j == 0) {
                    dp[i][j] = 1;
                } else {
                    dp[i][j] = min(min(dp[i - 1][j], dp[i][j - 1]), dp[i - 1][j - 1]) + 1;
                }
                maxSide = max(maxSide, dp[i][j]);
            }
        }
    }
    int maxSquare = maxSide * maxSide;
    return maxSquare;
}

int main(){
    return 0;
}
leetcode 69. x 的平方根_C++
#include<stdlib.h>
#include<stdio.h>

using namespace std;

// 这题出的有点离谱,感觉考的是数学
// 可惜,我数学拉垮了
// 我选择二分
int mySqrt(int x) {
    int low=0,high=x,ans=-1;
    while (low<=high)
    {
        int mid=low+(high-low)/2;
        if((long long)mid*(long long)mid<=x){
            low=mid+1;
            ans=mid;
        }else{
            high=mid-1;
        }
    }
    return ans;
}

int main(){
    printf("%d\n",mySqrt(4));
    return 0;
}

2020/5/10

leetcode 236. 二叉树的最近公共祖先_C++
#include<stdlib.h>
#include<stdio.h>
#include<vector>
#include<algorithm>
#include<queue>

using namespace std;
    
struct TreeNode {
    int val;
    TreeNode *left;
    TreeNode *right;
    TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};

TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
    if(root==nullptr) return root;
    if(root->val==p->val||root->val==q->val) return root;
    TreeNode *left=lowestCommonAncestor(root->left,p,q);
    TreeNode *right=lowestCommonAncestor(root->right,p,q);
        
    if(left!=NULL&&right!=NULL) return root;//如果p,q刚好在左右两个子树上
    if(left==NULL) return right;//仅在右子树
    return left;//仅在左子树
}

TreeNode* CreateTree(int a[],int n){
    if (n==0){
        return NULL;
    }
    TreeNode* root=new TreeNode(a[0]);
    queue<TreeNode*> q;
    q.push(root);
    int num=1;
    while(num<n){
        TreeNode* top=q.front();
        q.pop();
        if(top->left==NULL){
            if(a[num]!=-1){
                top->left=new TreeNode(a[num]);
                q.push(top->left);
            }
            num++;
        }
        if(num==n){
            break;
        }
        if(top->right==NULL){
            if(a[num]!=-1){
                top->right=new TreeNode(a[num]);
                q.push(top->right);
            }
            num++;
        }
    }
    return root;
}

int main(){
    int a[11]={3,5,1,6,2,0,8,-1,-1,7,4};
    TreeNode* root=CreateTree(a,11);
    TreeNode *p=new TreeNode(5);
    TreeNode *q=new TreeNode(1);
    TreeNode* ans=lowestCommonAncestor(root,p,q);
    printf("%d\n",ans->val);
    return 0;
}

2020/5/11

leetcode 50. Pow(x, n)_C++

算法笔记上有类似的,不过对幂次的范围没这题这么大,注意变量类型即可

#include<stdlib.h>
#include<stdio.h>
#include<vector>
#include<algorithm>

using namespace std;

double quick(double x,long long n){
    if(n==0) return 1.0;
    if(n%2==1) {
        return x*quick(x,n-1);
    }else{
        double mul=quick(x,n/2);
        return mul*mul;
    }
}

double myPow(double x, int n) {
    long long N=n;
    if(N>=0){
        return quick(x,N);
    }else{
        return 1.0/quick(x,-N); 
    }
}

int main(){
    double ans=myPow(2.0,-2147483648);
    printf("%f\n",ans);
    return 0;
}

2020/5/12

leetcode 155. 最小栈_C++

真摸鱼题

#include<stdio.h>
#include<stdlib.h>
#include<stack>
#include<algorithm>
#include<vector>

using namespace std;

class MinStack {
public:
    /** initialize your data structure here. */
    stack<int> minStack;
    stack<int> data;
    MinStack() {
        minStack.push(INT_MAX);
    }
    
    void push(int x) {
        data.push(x);
        minStack.push(min(minStack.top(), x));
    }
    
    void pop() {
        data.pop();
        minStack.pop();
    }
    
    int top() {
        int top=data.top();
        return top;
    }
    
    int getMin() {
        return minStack.top();
    }
};

int main(){
    return 0;
}

2020/5/15

leetcode 560. 和为K的子数组_C++
#include<stdio.h>
#include<stdlib.h>
#include<vector>

using namespace std;

int dp[20001];

// 前缀和
int subarraySum(vector<int>& nums, int k) {
    int ans=0;
    int n=nums.size();
    if(n==0) return ans;
    dp[0]=0;
    for(int i=1;i<=n;i++){
        dp[i]=dp[i-1]+nums[i-1];
    }
    for(int i=1;i<=n;i++){
        for(int j=0;j<i;j++){
            if(dp[i]-dp[j]==k){
                //printf("%d\n",dp[i]-dp[j]);
                ans++;
            }
        }
    }
    return ans;
}

int main(){
    int k=2;
    vector<int> nums={1,1,1};
    int ans=subarraySum(nums,k);
    printf("%d\n",ans);
    return 0;
}

2020/5/16

leetcode 25. K 个一组翻转链表_C++

感觉就是之前做过的题目的一个汇总,题解写的比自己本身的代码优雅,就记录一下题解好了

#include<stdio.h>
#include<stdlib.h>
#include<utility>
#include <iostream>
#include <fstream>

using namespace std;

struct ListNode {
    int val;
    ListNode *next;
    ListNode(int x) : val(x), next(NULL) {}
};

pair<ListNode*, ListNode*> myReverse(ListNode* head, ListNode* tail) {
    ListNode* prev = tail->next;
    ListNode* p = head;
    while (prev != tail) {
        ListNode* nex = p->next;
        p->next = prev;
        prev = p;
        p = nex;
    }
    return {tail, head};
}

ListNode* reverseKGroup(ListNode* head, int k) {
    ListNode* hair = new ListNode(0);
    hair->next = head;
    ListNode* pre = hair;

    while (head) {
        ListNode* tail = pre;
        // 查看剩余部分长度是否大于等于 k
        for (int i = 0; i < k; ++i) {
            tail = tail->next;
            if (!tail) {
                return hair->next;
            }
        }
        ListNode* nex = tail->next;
        pair<ListNode*,ListNode*> p;
        p = myReverse(head, tail);
        head=p.first;
        tail=p.second;
        // 把子链表重新接回原链表
        pre->next = head;
        tail->next = nex;
        pre = tail;
        head = tail->next;
    }
    return hair->next;
}

int main(){
    return 0;
}

2020/5/17

leetcode 210. 课程表 II_Go
package main

import "fmt"

// 拓扑排序
func findOrder(numCourses int, prerequisites [][]int) []int {
	// build the map
	ans := []int{}
	edges := make([][]int, numCourses)
	degree := make([]int, numCourses) // 入度
	for _, value := range prerequisites {
		edges[value[1]] = append(edges[value[1]], value[0])
		degree[value[0]]++
	}
	queue := []int{}
	for i := 0; i < numCourses; i++ {
		if degree[i] == 0 {
			queue = append(queue, i)
		}
	}
	// bfs
	for len(queue) > 0 {
		top := queue[0]
		queue = queue[1:]
		ans = append(ans, top)
		for _, v := range edges[top] {
			degree[v]--
			if degree[v] == 0 {
				queue = append(queue, v)
			}
		}
	}
	if len(ans) != numCourses {
		return []int{}
	}
	return ans
}

func main() {
	pre := [][]int{{1, 0}, {2, 0}, {3, 1}, {3, 2}}
	ans := findOrder(4, pre)
	fmt.Println(ans)
}

2020/5/18

leetcode 152. 乘积最大子数组_Go
package main

import "fmt"

// dp
func maxProduct(nums []int) int {
	n := len(nums)
	if n == 0 {
		return 0
	}
	maxF, minF, ans := nums[0], nums[0], nums[0]
	for i := 1; i < n; i++ {
		mx, mn := maxF, minF
		maxF = max(mx*nums[i], max(nums[i], mn*nums[i]))
		minF = min(mn*nums[i], min(nums[i], mx*nums[i]))
		ans = max(maxF, ans)
	}
	return ans
}

func max(a, b int) int {
	if a > b {
		return a
	}
	return b
}

func min(a, b int) int {
	if a > b {
		return b
	}
	return a
}

func main() {
	nums := []int{-4, -3, 2}
	ans := maxProduct(nums)
	fmt.Println(ans)
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值