学习笔记 算法

一、 双指针

  1. 普通双指针:两个指针往同一个方向移动(有时不是同一个方向)
  2. 对撞双指针:两个指针面对面移动
  3. 快慢双指针:慢指针+快指针
  4. 例:a = [1,4,5,7,9](有序数组) 两个数相加等于12,且两个数不能相同。
    对撞双指针:

例:检测是否为环形链表
快慢双指针:慢指针每次循环移动一格,快指针移动两格,最终是否相遇。

在这里插入图片描述

public class Solution {
    public boolean hasCycle(ListNode head) {
        if(head == null){
            return false;
        }   
        else{
            ListNode slow = head;
            ListNode fast = head;
            while(fast != null && fast.next != null){
                slow = slow.next;
                fast = fast.next.next;
                if (slow == fast){
                    return true;
                }
            }
            return false;
        }
    }
}
class Solution:
    def hasCycle(self, head: ListNode) -> bool:
        if head == None:
            return False
        else:
            slow = head
            fast = head
            while(fast != None and fast.next != None):
                slow = slow.next
                fast = fast.next.next
                if slow == fast:
                    return True
            return False

在这里插入图片描述

class Solution {
    public int numRescueBoats(int[] people, int limit) {
        Arrays.sort(people);
        int low = 0,high = people.length-1,count = 0;
        while(low<=high){
            if(people[low]+people[high]>limit){
                count += 1;
                high -= 1;
            }
            else{
                count += 1;
                low += 1;
                high -= 1;
            }
        }
        return count;
    }
}
class Solution:
    def numRescueBoats(self, people: List[int], limit: int) -> int:
        people.sort()
        low = 0
        high = len(people)-1
        count = 0
        while(low<=high):
            if people[low]+people[high]>limit:
                count += 1
                high -= 1
            else:
                low += 1
                high -= 1
                count += 1
        return count

二、 二分查找法

  1. 特点:一定要有序(数组元素单调增或单调减)

  2. 例题
    在这里插入图片描述

class Solution {
    public int search(int[] nums, int target) {
        int low = 0,high = nums.length-1,mod;
        while(low<=high){
            mod = (low+high)/2;
            if(nums[mod]== target) {
                return mod;
            }
            else if(nums[mod]>target){
                high = mod - 1;
            }
            else {
                low = mod + 1;
            }
        }
        return -1;
    }
}
class Solution:
    def search(self, nums: List[int], target: int) -> int:
        low = 0
        high = len(nums)-1
        while(low<=high):
            mod = (low+high)//2
            if nums[mod] == target:
                return mod
            elif nums[mod]>target:
                high = mod-1
            else:
                low = mod+1
        return -1

在这里插入图片描述

class Solution {
    public boolean searchMatrix(int[][] matrix, int target) {
        if(matrix == null || matrix.length == 0){
            return false;
        }
        else{
            int row = matrix.length;
            int col = matrix[0].length;
            int l = 0;
            int r = row*col-1;
            while(l<=r){
                int m = l+(r-l)/2;
                int element = matrix[m/col][m%col];
                if(element == target){
                    return true;
                }
                else if(element>target){
                    r = m-1;
                }
                else{
                    l = m+1;
                }
            }
            return false;
        }       
    }
}
class Solution:
    def searchMatrix(self, matrix: List[List[int]], target: int) -> bool:
        if matrix == None or len(matrix) == 0:
            return False
        else:
            row = len(matrix)
            col = len(matrix[0])
            l = 0
            r = row*col-1
            while(l<=r):
                m = l + (r-l)//2
                element = matrix[m//col][m%col]
                if element == target:
                    return True
                elif element > target:
                    r = m-1
                else:
                    l = m+1
            return False

三、滑动窗口

  1. 目的:减少while循环

  2. 应用:数组中的定长问题

  3. 例题:
    在这里插入图片描述

class Solution {
    public int minSubArrayLen(int target, int[] nums) {
        int res = nums.length+1;
        int i = 0,j = 0,total = 0;
        while(j<nums.length){
            total += nums[j];
            while(total>=target){
                res = Math.min(res, j - i + 1);
                total -= nums[i];
                i += 1;
            }
            j++;
        }
        if (res == nums.length+1){
            return 0;
        }
        else{
            return res;
        }
    }
}
class Solution:
    def minSubArrayLen(self, target: int, nums: List[int]) -> int:
        res = len(nums)+1
        count = 0
        i = 0
        j = 0
        while(j<len(nums)):
            count = count+nums[j]
            while(count>=target):
                res = min(res,j-i+1)
                count = count - nums[i]
                i = i+1
            j+=1
        if res == len(nums)+1:
            return 0
        else:
            return res

在这里插入图片描述

class Solution {
    public int maxVowels(String s, int k) {
        int i,count = 0,res = 0;
        char[] ch = s.toCharArray();
        String str = "aeiou";        
        for (i = 0;i<k;i++){
            if (str.indexOf(ch[i])!=-1){
                count+=1;
            }
                }
        res = Math.max(res,count);
        for (i = k;i<s.length();i++){
            if (str.indexOf(ch[i-k])!=-1){
                count -= 1;
            }
            if (str.indexOf(ch[i])!=-1){
                count += 1 ;
            }
            res = Math.max(res,count);
        }
        return res;
    }
}
class Solution:
    def maxVowels(self, s: str, k: int) -> int:
        i = 0
        count = 0
        res = 0
        for i in range(k):
            if s[i] in "aeiou":
                count+=1
        res = max(res,count)
        for i in range(k,len(s)):
            if s[i-k] in "aeiou":
                count -= 1
            if s[i] in "aeiou":
                count += 1 
            res = max(res,count)
        return res

四、递归

  1. 定义:函数直接或者间接调用自己

  2. 四个要素:

  • 接受的参数
  • 返回值
  • 终止条件
  • 递归拆解:如何递归下一层
recursion(int n):	#参数
	if n == 0:		#终止条件
		return 0	
	m = recursion(n-1)	#拆解
	return m		#返回的值
  1. 例题
    在这里插入图片描述
class Solution {
    public int fib(int n) {
        if(n<2){
            return n;
        }
        else{
            return fib(n-1)+fib(n-2);
        }
    }
}
class Solution:
    def fib(self, n: int) -> int:
        if n<2:
            return n
        else:
            sum = self.fib(n-1)+self.fib(n-2)
            return sum

在这里插入图片描述

class Solution {
    public ListNode reverseList(ListNode head) {
        ListNode dummy = new ListNode(0);
        dummy.next = head;
        while(head != null && head.next != null){
            ListNode dnext = dummy.next;
            ListNode hnext = head.next;
            dummy.next = head.next;
            head.next = hnext.next;
            hnext.next = dnext;
        }
        return dummy.next; 
    }
}
class Solution:
    def reverseList(self, head: ListNode) -> ListNode:
        dummy = ListNode(0)
        dummy.next = head
        while(head != None and head.next!= None):
            dnext = dummy.next
            hnext = head.next
            dummy.next = hnext
            head.next = hnext.next
            hnext.next = dnext
        return dummy.next

五、分治法

大问题切割成一个个小问题,最后再合并。
用到了递归,自己调用自己。

在这里插入图片描述

class Solution:
    def getNajority(nums,left,right):
        if left == right:
            return nums[left]
        else:
            mid = left+(right-left)//2
            leftNajority = getNajority(nums,left,right)
            rightNajority = getNajority(nums,mid+1,right)
            if leftNajority == rightNajority:
                return leftNajority
            else:
                leftcount = 0
                rightcount = 0
                for i in nums[left,right]:
                    if i == leftNajority:
                        leftcount+=1
                    elif i == rightNajority:
                        rightcount+=1
                if leftcount > rightcount:
                    return leftNajority
                else:
                    return rightNajority
    def majorityElement(self, nums: List[int]) -> int:
        return getNajority(nums,0,len(nums)-1)

六、回溯法

类似枚举,一层一层向下递归,尝试搜索答案。

  • 找到答案后,尝试别的可能或返回答案。
  • 找不到答案,则返回上一层递归,尝试别的路径。

七、深度优先搜索算法 (DFS)

  1. 用到了递归的思想。
  2. DFS:从root节点开始,尽可能深的搜索每一个分支。(把一个分支的结果搜索完,再去看下一个分支)
  3. 主要应用:
  • 二叉树搜索
  • 图搜索
  1. 例:走迷宫
  2. DFS和回溯算法的区别:回溯算法 = DFS + 剪枝

八、广度优先搜索算法(BFS)

  1. 主要思想:层层递进,一层一层遍历
  2. 主要应用:
  • 二叉树搜索
  • 图搜索
  1. DFS与BFS的区别:
    侧重点不同:
  • DFS:分支
  • BFS:层

九、并查集(Union Find)

  1. Union:合并两个元素为同一个根节点
  2. Find:找到某个元素的根节点

十、贪心算法(Greedy)

  1. 核心:
  • 每一步做出的都是当前看起来最好的选择
  • 只是局部的最优选择
  • 而不是整体的最优选择
  1. 例:零钱兑换 最少硬币的情况,应当尽可能取大的硬币

十一、算法记忆化(Memoization)

  1. 目的:减少重复计算

十二、动态规划

  • 题型千变万化
  • 思想千变万化

动态规划三要素:

  • 初始状态(可能是一个数,也可能是多个数)
  • 方程式(状态转移函数)
  • 终止状态
    应用:
  1. 计数:有多少种方式/方法
    例:机器人从左上角到右下角有多少个路径
  2. 求最值:最大值/最小值
    例:机器人从左->右路径的最大数字和
  3. 求存在性:是否存在某个可能
    例:是否存在机器人从左->右的路径

在这里插入图片描述

class Solution {
    public int fib(int n) {
        if(n<2){
            return n;
        }
        else{
            int dp[] = new int[n+1];
            dp[0] = 0;
            dp[1] = 1;
            for(int i=2;i<n+1;i++){
                dp[i] = dp[i-1] + dp[i-2];
            }
            return dp[n];
        }
    }
}

在这里插入图片描述

class Solution {
    public int uniquePaths(int m, int n) {
        int [][] dp =new int[m][n];
        dp[0][0] = 1;
        for(int i=0;i<m;i++){
            for(int j=0;j<n;j++){
                if(i-1>=0 && i-1<m){
                    dp[i][j] = dp[i][j]+dp[i-1][j];
                }
                if(j-1>=0 && j-1<n){
                    dp[i][j] = dp[i][j]+dp[i][j-1];
                }
            }
        }
        return dp[m-1][n-1];
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值