1.广度优先搜索
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public List<List<Integer>> levelOrder(TreeNode root) {
List<List<Integer>> res = new ArrayList<>();
if(root == null)
return res;
Queue<TreeNode> q = new LinkedList<>();
q.offer(root);
while(!q.isEmpty()) {
List<Integer> tr = new ArrayList<>();
int n = q.size();
for(int i = 0;i < n;i++) {
TreeNode r = q.poll();
tr.add(r.val);
if(r.left != null) {
q.offer(r.left);
}
if(r.right != null) {
q.offer(r.right);
}
}
res.add(tr);
}
return res;
}
}
2.链表知识
1.进制:709 + 201 的反转链表为 907 + 102,得出一个一模一样反转和 例如9 + 1 >= 10,则该位置取加起来数字的个位数,后面的值交给下一位来相加
题目:
给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。
请你将两个数相加,并以相同形式返回一个表示和的链表。
你可以假设除了数字 0 之外,这两个数都不会以 0 开头。
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
ListNode res = null,temp = null;
int c = 0;
while(l1 != null || l2 != null) {
int a = l1 != null ? l1.val : 0;
int b = l2 != null ? l2.val : 0;
int sum = a + b + c;
if(res == null) {
res = temp = new ListNode(sum % 10);
}else {
temp.next = new ListNode(sum % 10);
temp = temp.next;
}
c = sum / 10;
if(l1 != null) {
l1 = l1.next;
}
if(l2 != null) {
l2 = l2.next;
}
}
if(c > 0) {
temp.next = new ListNode(c);
}
return res;
}
}
3.
题目:
给定一个经过编码的字符串,返回它解码后的字符串。
编码规则为: k[encoded_string],表示其中方括号内部的 encoded_string 正好重复 k 次。注意 k 保证为正整数。
你可以认为输入字符串总是有效的;输入字符串中没有额外的空格,且输入的方括号总是符合格式要求的。
此外,你可以认为原始数据不包含数字,所有的数字只表示重复的次数 k ,例如不会出现像 3a 或 2[4] 的输入。
示例 1:
输入:s = "3[a]2[bc]"
输出:"aaabcbc"
示例 2:
输入:s = "3[a2[c]]"
输出:"accaccacc"
示例 3:
输入:s = "2[abc]3[cd]ef"
输出:"abcabccdcdcdef"
示例 4:
输入:s = "abc3[cd]xyz"
输出:"abccdcdcdxyz"
1.栈解决
class Solution {
public String decodeString(String s) {
StringBuilder res = new StringBuilder();
int multi = 0;
//用于存放倍数
LinkedList<Integer> sta_mul = new LinkedList<>();
//用于存放一段字符串
LinkedList<String> sta_res = new LinkedList<>();
for(Character c : s.toCharArray()) {
if(c == '[') {
sta_mul.addLast(multi);
sta_res.addLast(res.toString());
multi = 0;
res = new StringBuilder();
}else if(c == ']') {
StringBuilder tmp = new StringBuilder();
int now_mul = sta_mul.removeLast();
for(int i = 0;i < now_mul;i++) {
tmp.append(res);
}
res = new StringBuilder(sta_res.removeLast() + tmp);
}else if(c >= '0' && c <= '9') {
multi = multi * 10 + Integer.parseInt(c + "");
}else {
res.append(c);
}
}
return res.toString();
}
}
2.递归
class Solution {
public String decodeString(String s) {
return dfs(0,s)[0];
}
public String[] dfs(int i,String s) {
StringBuilder res = new StringBuilder();
int mul = 0;
while(i < s.length()) {
if(s.charAt(i) >= '0' && s.charAt(i) <= '9') {
mul = mul * 10 + Integer.parseInt(String.valueOf(s.charAt(i)));
}else if(s.charAt(i) == '[') {
//递归获取[]之间的字符串
String[] arr = dfs(i + 1,s);
i = Integer.parseInt(arr[0]);
String re = arr[1];
//也将mul--为0以便下次操作
while(mul > 0) {
res.append(re);
mul--;
}
}else if(s.charAt(i) == ']') {
return new String[]{String.valueOf(i),res.toString()};
}else {
res.append(String.valueOf(s.charAt(i)));
}
i++;
}
return new String[]{res.toString()};
}
}
4.动态规划
给你一个字符串 s 和一个字符串列表 wordDict 作为字典。请你判断是否可以利用字典中出现的单词拼接出 s 。
注意:不要求字典中出现的单词全部都使用,并且字典中的单词可以重复使用。
示例 1:
输入: s = "leetcode", wordDict = ["leet", "code"]
输出: true
解释: 返回 true 因为 "leetcode" 可以由 "leet" 和 "code" 拼接成。
示例 2:
输入: s = "applepenapple", wordDict = ["apple", "pen"]
输出: true
解释: 返回 true 因为 "applepenapple" 可以由 "apple" "pen" "apple" 拼接成。
注意,你可以重复使用字典中的单词。
示例 3:
输入: s = "catsandog", wordDict = ["cats", "dog", "sand", "and", "cat"]
输出: false
class Solution {
public boolean wordBreak(String s, List<String> wordDict) {
int length = s.length();
Set<String> set = new HashSet(wordDict);
boolean[] dp = new boolean[length + 1];
dp[0] = true;
//i从1开始不仅为了substring还为了dp数组
for(int i = 1;i <= length;i++) {
for(int j = 0;j < i;j++) {
if(dp[j] && wordDict.contains(s.substring(j,i))) {
//i前面的都符合
dp[i] = true;
break;
}
}
}
return dp[length];
}
}
5.二分法
给你一个 下标从 0 开始 的整数数组 candies 。数组中的每个元素表示大小为 candies[i] 的一堆糖果。你可以将每堆糖果分成任意数量的 子堆 ,但 无法 再将两堆合并到一起。
另给你一个整数 k 。你需要将这些糖果分配给 k 个小孩,使每个小孩分到 相同 数量的糖果。每个小孩可以拿走 至多一堆 糖果,有些糖果可能会不被分配。
返回每个小孩可以拿走的 最大糖果数目 。
示例 1:
输入:candies = [5,8,6], k = 3
输出:5
解释:可以将 candies[1] 分成大小分别为 5 和 3 的两堆,然后把 candies[2] 分成大小分别为 5 和 1 的两堆。现在就有五堆大小分别为 5、5、3、5 和 1 的糖果。可以把 3 堆大小为 5 的糖果分给 3 个小孩。可以证明无法让每个小孩得到超过 5 颗糖果。
示例 2:
输入:candies = [2,5], k = 11
输出:0
解释:总共有 11 个小孩,但只有 7 颗糖果,但如果要分配糖果的话,必须保证每个小孩至少能得到 1 颗糖果。因此,最后每个小孩都没有得到糖果,答案是 0 。
class Solution {
public int maximumCandies(int[] candies, long k) {
int len = candies.length;
long sum = 0;
for(int i = 0;i < len;i++) {
sum += candies[i];
}
if(sum < k)
return 0;
int res = 0;
Arrays.sort(candies);
int left = 1;
int right = (int) (sum / k);
while(left <= right) {
long now = 0;
int mid = left + (right - left) / 2;
for(int i = len-1;i >=0;i--) {
if(candies[i] < mid)
break;
now += candies[i] / mid;
}
if(now >= k) {
left = mid + 1;
res = mid;
}else {
right = mid - 1;
}
}
return res;
}
}