算法

双向BFS

leetcode  单词接龙

桶排序

leetcode 164 最大间距
leetcode 220

二分法

别人总结的二分法
山脉数组中查找目标

快慢指针

快乐数(类似链表找循环)

前缀和 (配合哈希表)

注意与滑动窗口的区别
leetcode 560
leetcode 974

辅助栈

涉及到嵌套 和顺序有关的时候 (也可考虑递归)
leetcode 394

位运算

leetcode 201 数字范围按位与 (本质找公共前缀)
n&(n-1)把最后一个1 变0。
n&(-n) n&(~n+1) 保留最后一个1 剑指offer 数组中数字出现的次数

素数(厄拉多塞筛法)

leetcode 204计数质数 有点类似的(丑数系列)
偶数一定不是质数,
奇数有的也不是。
所以代码中只看奇数,没有考虑偶数

class Solution {    
	public int countPrimes(int n) {        
		boolean[]  temp = new boolean[n];        
		int res = 0;        
		if(n>2){            
			res++;        
		}        
		for(int  i =3;i<n;i=i+2){            
			if(!temp[i]){                
				for(int j = 3;j*i<n;j=j+2){                    
					temp[i*j] = true;                
				}                
			res++;            
			}        
		}        
		return res;    
	}
}

背包问题

leetcode 416
leetcode 494
01背包 完全背包 总结!

双指针(滑动窗口) 和 dp

看看符不符合滑动窗口,不符合考虑dp 以nums【i】结尾的。。。 子序列 子数组啥的

和最大子数组 乘积最大子数组 最短子数组 各种子数组问题 通常:1.滑动窗口 2.前缀和

treeset(ceiling(E e),floor(E e))

leetcode 220

单调队列 单调栈

存放下标
leetcode 239 (优先队列 都是为了O(1)取得最大值)

矩形面积,正方形面积

边界是一 或者全部是一

博弈论的动态规划问题

leetcode 292 入门问题
几个基础博弈:

巴什博弈 (字节跳动夏令营第一批笔试题)

		问题:有一堆石子n个 , 每次可以取1~m个石子 , 没有石子可取的那方输 , 问第一个取的人的输赢
		解决方法:有一堆 n 个物品,两人轮流从堆中取物品,每次取 x 个 ( 1 ≤ x ≤ m)最多取m个。
		最后取光者获胜。如果有 n = m + 1, 一次至多取 m 个,所以无论先取者,取了多少个,一定还剩下 x 个( 1 ≤ x ≤ m)。
		所以,后取者必胜。因此我们发现了取胜的秘诀:如果我们把 n 表示为 n = (m + 1) * r + s 。(0 ≤ s < m , r ≥ 0)。
		先取者拿走 s 个, 后取者拿走 k 个 (1 ≤ k ≤ m),那么先取者 再 拿走 m + 1 - k 个。结果还剩下 ( m + 1 ) * ( r - 1 ) 个。
		我们只要始终给对手留下 m + 1 的倍数,那么先取者肯定必胜。 现在 我们可以知道,如果 s = 0,那么后取者必胜。 否则 先取者 必胜。
		变形(最后取得输):
		留一块给对面
		(n-1)%(m+1);

威佐夫博弈

有两堆各若干个物品,两个人轮流从某一堆或同时从两堆中取同样多的物品,规定每次至少取一个,多者不限,最后取光者得胜。
(n1,n2) 格局
解法: p=(sprt(5)+1)/2; 1.618
差值*p==最小值 则 后手赢

尼姆博弈

有k堆各若干个物品,两个人轮流从某一堆取任意多的物品,规定每次至少取一个,多者不限,最后取光者得胜。

斐波那契博弈(字节跳动夏令营第二批笔试题)

有一堆石子,两个人轮流从其中取走一定的石子,取走最后所有石子的人为赢家,不过得遵循如下规则:
1.第一次取不能取完,至少取1颗.
2.从第二次开始,每个人取的石子数至少为1,至多为对手刚取的石子数的两倍。

解决方法:当n为Fibonacci数时,先手必败。否则先手必胜

证明:根据“Zeckendorf定理”(齐肯多夫定理):任何正整数可以表示为若干个不连续的Fibonacci数之和。如n=83 = 55+21+5+2,假如先手取2颗,那么后手无法取5颗或更多,而5是一个Fibonacci数,那么一定是先手取走这5颗石子中的最后一颗,同理,接下去先手取走接下来的后21颗中的最后一颗,再取走后55颗中的最后一颗,那么先手赢。

2.3.4 的幂

循环 (while(n%x==0){
n = n/x;
}
判断是不是1

换底公式 log10(n)/log10(x) 是不是整数
位运算(2,4)

马拉车算法

leetcode 5

KMP算法

leetcode 28
左神 算法书

原地hash

这种题一般有这条件: 1 ≤ a[i] ≤ n ( n = 数组大小 )
leetcode 41
缺失的第一个正数
leetcode 448
找到所有数组中消失的数字
leetcode442
数组中重复的数字

规律:

找重复数字: add(nums[i]);
找缺失数字:add(i+1);

大数相乘(字符串相乘)

leetcode 43

实现除法(不用乘除)

两数相除
普通的递减太慢了,要加倍减。结合递归
注意边界问题!

转化为负数(处理边界问题)
方法一

public int divide(int dividend, int divisor) {
		int ans = -1;
		int sign = 1;
		if (dividend > 0) {
			sign = opposite(sign);
			dividend = opposite(dividend);
		}
		if (divisor > 0) {
			sign = opposite(sign);
			divisor = opposite(divisor);
		}   
		
		int origin_dividend = dividend;
		int origin_divisor = divisor;
		if (dividend > divisor) {
			return 0;
		} 
		
		dividend -= divisor;
		while (divisor >= dividend) {
			ans = ans + ans;
			divisor += divisor;
			dividend -= divisor;
		}
    	//此时我们传进的是两个负数,正常情况下,它就返回正数,但我们是在用负数累加,所以要取相反数
		int a = ans + opposite(divide(origin_dividend - divisor, origin_divisor));
		if(a == Integer.MIN_VALUE){
			if( sign > 0){
				return Integer.MAX_VALUE;
			}else{
				return Integer.MIN_VALUE;
			}
		}else{
			if(sign > 0){
				return opposite(a);
			}else{
				return a;
			}
		}
	}
	public int opposite(int x) {
		return ~x + 1;
	}
}

方法二
(直接从最大开始)

class Solution {
    public int divide(int dividend, int divisor) {
        if(dividend==0){
            return 0;
        }
        if(dividend == Integer.MIN_VALUE && divisor == -1){
            return Integer.MAX_VALUE;
        }
        boolean  flag = (dividend^divisor)<0;
        long t = Math.abs((long) dividend);
        long d= Math.abs((long) divisor);
        int result = 0;
        for(int i =31;i>=0;i--){
            if((t>>i) >= d){
                result+=1<<i;
                t-=d<<i;
            }
        }return flag?-result : result;
    }
}

进制转化(一个取余,除。一个相乘,加)

10转26(不是一般的26)

class Solution {
    public String convertToTitle(int n) {
        StringBuilder ans = new StringBuilder();
        while(n!=0){
            n--;
            ans.append((char)(n%26+'A'));
            n /=26;
        }
        return ans.reverse().toString();
    }
}

26 转 10

class Solution {
    public int titleToNumber(String s) {
        int ans = 0;
        int  j =0;
        for(int i  = s.length()-1;i>=0;i--){
            ans += (int)(s.charAt(i)-(int)('A')+1)*Math.pow(26,j);
            j++;
        }
        return ans;
    }
}

小数的转换
迭代地 X乘h,直到小数部分为0时停止乘h,将 每次得到的整数部分 正序排列 即为答案 (有时小数部分永远不为0)

整数拆分(剪绳子)

动态规划

class Solution {
    public int integerBreak(int n) {
        int[] dp = new int[n+1];
        for(int i =2;i<=n;i++){
            for(int j  =1 ;j<i;j++){
            //继续细分或者不分
                dp[i] = Math.max(dp[i],Math.max(dp[i-j]*j,(i-j)*j));
            }
        }
        return dp[n];
    }
}

数学规律
① 当所有拆分出的数字相等时,乘积最大。
“算术几何均值不等式” ,等号当且仅当 n_1 = n_2 = … = n_an
时成立。
② 最优拆分数字为 3。
算出来的。
取最大值时, 乘积达到最大值。

最优: 3。把数字 nn 可能拆为多个因子 3 ,余数可能为 0,1,2 三种情况。
次优: 2 。若余数为 2 ;则保留,不再拆为 1+1 。
最差: 1 。若余数为 1;则应把一份 3 + 1替换为 2 + 2,因为2×2>3×1。

		if(n<=3){
            return n-1;
        }
        int a =  n/3;
        int b = n%3;
        if(b==0){
            return (int)Math.pow(3,a);
        }else if(b==2){
            return ((int)Math.pow(3,a))*2; 
        }else{
            return ((int)Math.pow(3,a-1))*4;
        }

比特位计数

位运算+动态规划 涨姿势了


class Solution {
    public int[] countBits(int num) {
        int[] dp = new int[num+1];
        dp[0] = 0;
        for(int i = 1;i<dp.length;i++){
        //这一句
            dp[i] = dp[i&(i-1)]+1;
        }
        return dp;
    }
}

卡特兰数

leetcode96 不同的搜索二叉树
卡特兰数,及应用

拓扑排序

「拓扑排序」是专门应用于有向图的算法;
这道题用 BFS 和 DFS 都可以完成,只需要掌握 BFS 的写法就可以了,BFS 的写法很经典;
BFS 的写法就叫「拓扑排序」,这里还用到了贪心算法的思想,贪的点是:当前让入度为 0 的那些结点入队;
「拓扑排序」的结果不唯一;
删除结点的操作,通过「入度数组」体现,这个技巧要掌握;
「拓扑排序」的一个附加效果是:能够顺带检测有向图中是否存在环,这个知识点非常重要,如果在面试的过程中遇到这个问题,要把这一点说出来。

主要两部分:
1.入度数组。
2.邻接表。
leetcode 207 课程表
检测是否是DAG(有向无环图)

leetcode 210课程表Ⅱ

优先队列+贪心

和前两个不一样,没有用到拓扑排序。用的 是优先队列+贪心(先用优先队列控制一个变量)
leetcode 630 课程表Ⅲ

前缀树(字典树)

leetcode208 实现Trie(前缀树)
重点两个
struct TrieNode {
bool isEnd; //该结点是否是一个串的结束
TrieNode* next[26]; //字母映射表
};

leetcode211 添加与搜索单词
前缀树+通符串匹配

leetcode 212单词搜索Ⅱ
将回溯与前缀树结合起来 ,效率更高,不用每个去遍历一遍

数组中的第K个最大元素
1.使用 java自带api
2.自己实现堆(heapInsert和heapify)
3.基于快速排序的选择算法

还有数据流中的中位数 ,用到了大顶堆和小顶堆

二叉搜索树

leetcode 220 存在重复元素
有两个变化量,想办法控制住一个。类比之前单词搜索Ⅱ(用优先队列)。
借助了treeset 的ceillng()方法。

kmp和马拉车

leetcode214 最短回文串(类似的题还有在末尾加字符)
kmp和马拉车算法都可以用,这题本质是求包括开头的最长回文串。
kmp 主要借助了next 数组,将两个字符串叠加,找最大的next.
马拉车算法原理:看出没出最大右边界,出了的话中间扩散,没出的话借用对称的信息。

计算器问题

1.中缀表达式 转化为后缀表达式,后缀表达式 容易求解。
中缀表达式转后缀表达式
中缀表达式a + b*c + (d * e + f) * g,其转换成后缀表达式则为a b c * + d e * f + g * +。

转换过程需要用到栈,具体过程如下:

1)如果遇到操作数,我们就直接将其输出。

2)如果遇到操作符,则我们将其放入到栈中,遇到左括号时我们也将其放入栈中。

3)如果遇到一个右括号,则将栈元素弹出,将弹出的操作符输出直到遇到左括号为止。注意,左括号只弹出并不输出。

4)如果遇到任何其他的操作符,如(“+”, “*”,“(”)等,从栈中弹出元素直到遇到发现更低优先级的元素(或者栈为空)为止。弹出完这些元素后,才将遇到的操作符压入到栈中。有一点需要注意,只有在遇到" ) “的情况下我们才弹出” ( “,其他情况我们都不会弹出” ( "。

5)如果我们读到了输入的末尾,则将栈中所有元素依次弹出。
2.双栈

使用两个栈,stack0 用于存储操作数,stack1 用于存储操作符
从左往右扫描,遇到操作数入栈 stack0
遇到操作符时,如果当前优先级低于或等于栈顶操作符优先级,则从 stack0 弹出两个元素,从 stack1 弹出一个操作符,进行计算,将结果并压入stack0,继续与栈顶操作符的比较优先级。
如果遇到操作符高于栈顶操作符优先级,则直接入栈 stack1
遇到左括号,直接入栈 stack1。
遇到右括号,则从 stack0 弹出两个元素,从 stack1 弹出一个操作符进行计算,并将结果加入到 stack0 中,重复这步直到遇到左括号

摩尔投票

出现次数超过一半的数

出现次数超过n/3的数

摩尔投票法 两个步骤 : 抵消阶段 和 投票阶段

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。
经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值