本文是牛客网左神算法中级班学习笔记。
【思路】
先放入set中(去重),然后遍历一遍set就OK了。
public static List<List<Integer>> allPair(int[] a, int k){
HashSet<Integer> set = new HashSet<Integer>();
for(int i = 0; i < a.length; i++){
set.add(a[i]);
}
List<List<Integer>> res = new ArrayList<>();
for(Integer cur : set){
if(set.contains(cur + k)){
res.add(Arrays.asList(cur, cur+k));
}
}
return res;
}
【扩展】
给定一组字符串(只含有小写字母),根据含有字母种类不同进行分类。
思路:一共只有26个小写字母,那么可以用26个位就可以代表所有情况了,对每个字符串进行遍历,字母a-z对应第0-25位(这个值是count |= 1 << (str[i] - ‘a’)),分别进行赋值。生成一共map,key是对应的26位数的大小,value是对应的字符串list。(位简化)
思路:建立哈希表(值是list类型),对每个字符串进行排序去重,作为key,原字符串加入对应的list中。(直接法)
【暴力递归】
public static int convertWays(int num){
if(num < 1){
return 0;
}
return process(String.valueOf(num).toCharArray(), 0);
}
// process(chs, index)表示字符串chs,从index下标到chs末尾可以转换的字符串个数
// 【暴力递归】
public static int process(char[] chs, int index){
if(index == chs.length){
return 1; // 递归终止,加1
}
if(chs[index] == '0'){
return 0;
}
int res = process(chs, index+1);
if(index == chs.length - 1){
return res;
}
if((chs[index] - 'a')*10 + (chs[index+1] - 'a') <= 26){
res += process(chs, index+2);
}
return res;
}
【动态规划】
// 【动态规划】
public static int dpWays(int num){
if(num < 1){
return 0;
}
char[] chs = String.valueOf(num).toCharArray();
int[] dp = new int[chs.length+1];
dp[chs.length] = 1;
dp[chs.length-1] = dp[chs.length-1] == '0' ? 0 : 1;
for(int i = chs.length - 2; i >= 0; i--){
if(chs[i] == '0'){
dp[i] = 0;
}else{
dp[i] = dp[i+1] + ((chs[i] - 'a')*10 + (chs[i+1] - 'a')) <= 26 ? dp[i+2] : 0;
}
}
return dp[0];
}
public static void sortStackByStack(Stack<Integer> stack){
Stack<Integer> help = new Stack<Integer>();// 辅助栈从栈顶到栈底依次变大
while(!stack.isEmpty()){
int cur = stack.pop();
while(!help.isEmpty() && cur > help.peek()){
stack.push(help.pop());
}
help.push(cur);
}
while(!help.isEmpty()){
stack.push(help.pop());
}
}
【打表找规律】
先根据草的份数,来看下先手还是后手是赢家!!!
草份数 | 赢家 |
---|---|
0 | 后手 |
1 | 先手 |
2 | 后手 |
3 | 先手 |
4 | 先手 |
import java.util.*;
public class Main{
public static void main(String[] args){
for(int i = 0; i <= 50; i++){
System.out.println(winner1(i));
}
}
// 站在先手的角度
public static String winner1(int n){
if(n < 5){
return (n == 0 || n == 2) ? "后手" : "先手";
}
int base = 1;
while(base <= n){
// 如果先手的子过程中后手赢了(先手子过程的后手就是先手)
if(winner1(n-base).equals("后手")){
return "先手";
}
// 防止base*4之后越界
if(base > n / 4){
break;
}
base *= 4;
}
return "后手";
}
}
规律是“后先后先先”。
public static String winner2(int n){
if(n%5 ==0 || n%5 == 2){
return "后手";
}
return "先手";
}
【递归法】
public static int maxSumRecursive(Ndoe head){
return process(head, 0);
}
// 当前节点是x,pre是从头结点到x节点累加和(除x节点外)
public static int process(Node x, int pre){
if(x == null){
return Integer.MIN_VALUE;
}
if(x.left == null && x.right == null){
return pre + x.value;
}
int leftMax = process(x.left, pre+x.value);
int rightMax = process(x.right, pre+x.value);
return Math.max(leftMax, rightMax);
}
【非递归法】
// 非递归先序遍历同时,计算从根节点到当前节点的路径和
public static int maxSumUnrecursive(Node head){
int max = Integer.MIN_VALUE;
HashMap<Node, Integer> sumsMap = new HashMap<>();
if(head != null){
Stack<Node> stack = new Stack<>();
stack.push(head);
sumsMap.put(head, head.value);
while(!stack.isEmpty()){
head = stack.pop();
if(head.left == null && head.right == null){
max = Math.max(max, sumsMap.get(head));
}
if(head.right != null){
sumsMap.put(head.right, sumsMap.get(head)+head.right.value);
stack.push(head.right);
}
if(head.left != null){
sumsMap.put(head.left, sumsMap.get(head)+head.left.value);
stack.push(head.left);
}
}
}
return max == Integer.MIN_VALUE ? 0 : max;
}