牛客网左神算法中级班学习笔记(第二章)

本文是牛客网左神算法中级班学习笔记。
在这里插入图片描述

【思路】
先放入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;
	}
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值