其实就是一个队列,比如例题中的 abcabcbb,进入这个队列(窗口)为 abc 满足题目要求,当再进入 a,队列变成了 abca,这时候不满足要求。所以,我们要移动这个队列!
如何移动?
我们只要把队列的左边的元素移出就行了,直到满足题目要求!
一直维持这样的队列,找出队列出现最长的长度时候,求出解
涉及题目:3
首先使用哈希表存储每个数字对应的所有可能的字母,然后进行回溯操作。
回溯过程中维护一个字符串,表示已有的字母排列(如果未遍历完电话号码的所有数字,则已有的字母排列是不完整的)。该字符串初始为空。每次取电话号码的一位数字,从哈希表中获得该数字对应的所有可能的字母,并将其中的一个字母插入到已有的字母排列后面,然后继续处理电话号码的后一位数字,直到处理完电话号码中的所有数字,即得到一个完整的字母排列。然后进行回退操作,遍历其余的字母排列。
1.栈
建立一个prev保留为头结点,最后方便返回,将链表进栈,然后依次出栈,出到第n次便找到自己要找的节点了
2.双指针法
使用一前一后两个指针,两个指针相差n个节点,当后指针到末尾时,前指针便是要删除节点的位置
3.统计长度法
先遍历一遍统计长度,得到正向的位置,然后删除即可。
使用递归法,将其划分为比较两个节点的值,比较只有,选择较小作为最新的节点,再调用自身来进行比较,
结束状态为有一个列表为空
1.回溯法
将这个问题当做一个向长度为2N的列表中添加字符串,维护一个列表S,当列表S长为2N的时候,将该列表拼接成字符串添加到ans中
往每个位置添加字符串的情况有两种:添加 ‘(’ 或 ‘)’,遍历完一种情况,进行出栈来计算另一种情况。
其中每次都要检查进栈的字符串是否合法,即初始化bal = 0,遍历字符串列表,若出现bal<0的不符合,直接返回。
2.回溯法优化
将这个问题当做一个向长度为2N的列表中添加字符串,维护一个列表S,当列表S长为2N的时候,将该列表拼接成字符串添加到ans中
往每个位置添加字符串的情况有两种:添加 ‘(’ 或 ‘)’。
优化的部分是:left(左括号数)小于n,便可以添加;right(右括号数)小于左括号数才可以添加。
1.递归+分治
首先使用递归法,每次的比较两个节点值,选择值小的节点,该节点的next调用的递归函数,其中一个节点改为的该节点的下一个传入进去。
分治法:每次两两合并链表,存到新的list中,如果为奇数,将最后一个直接放入进去,最终为长度为1表示合并成一个链表了。
对于有序区间使用双指针翻转区间:第一个指针指向列表的开头,第二个指针指向列表的末尾,每次的交换两个指针指向的数,然后两个指针分别往中间位置挪动一位,结束条件是:右边的指针的位置不再大于左边指针的位置。
动态规划
DP转移方程:
(1) 当s[i]’(‘时,一定不是结束的状态的,对最终dp结果无影响,后面的dp不会用到’('的dp的值
(2) 当s[i]’)‘时:
(1) dp[i] = dp[i-2]+2 ---------当s[i-1]’(’
(2) dp[i] = dp[i-1]+dp[i-dp[i-1]-2]+2 ------ 当s[i-1]’)’且s[i-dp[i-1]-1]==’(’
边界情况,每个转移情况都要检查是否越界,如果越界,并对越界的情况进行处理
栈
栈中最顶部的位置的存储的为上一未匹配的右括号的位置,因此在栈中首先要加入-1,表示上一个未匹配右括号位置为-1
当s[i] == ‘(’, 将其进栈
当s[i] == ‘)’,进行出栈,如果栈为空:说明出栈的不是’(‘的位置,将该’('的位置进栈,如果不为空,将该右括号的位置减去栈中顶部位置为长度。
贪心策略
在此方法中,我们利用两个计数器 left 和right 。首先,我们从左到右遍历字符串,对于遇到的每个‘(’,我们增加left 计数器,对于遇到的每个 ‘)’ ,我们增加right 计数器。每当left 计数器right 计数器相等时,我们计算当前有效字符串的长度,并且记录目前为止找到的最长子字符串。当 right 计数器比eft 计数器大时,我们将 left 和right 计数器同时变回0。
这样的做法贪心地考虑了以当前字符下标结尾的有效括号长度,每次当右括号数量多于左括号数量的时候之前的字符我们都扔掉不再考虑,重新从下一个字符开始计算,但这样会漏掉一种情况,就是遍历的时候左括号的数量始终大于右括号的数量,即 (() ,这种时候最长有效括号是求不出来的。
解决的方法也很简单,我们只需要从右往左遍历用类似的方法计算即可,只是这个时候判断条件反了过来:
当 left 计数器比right 计数器大时,我们将left 和right 计数器同时变回 0
当left 计数器right 计数器相等时,我们计算当前有效字符串的长度,并且记录目前为止找到的最长子字符串
1.递归+回溯+DFS
首先将缺少数字的位置加入到数组中,将每个数字的行、列、box中对应的值进行设置为False表示该行、列、box没有该值。
设置一个valid值,使用nolocal声明,在函数中共享,当dfs中的值与empty的数组的相等时说明在所有的位置都以填入了合适的数字,设置valid为True是结束状态;针对每个空白位置,进行1-9的数字遍历,即分别填入空白位置中(将行、列、box该位置的值更新为True,更新board),进行dfs下一个位置的递归,下一个位置的不成功,将行、列、box该位置的值更新为False,进行下一个数字的尝试。dfs结束条件:valid为True时,停止遍历直接return,遍历完之后没有成功的话进行return,使上一状态重新选择值。
1.递归+回溯+剪枝
使用递归加回溯的方法,首先对数组的进行从大到下的排序,遍历所有的候选数,(1)如果数字比target大结束遍历,因为后面的数也比target大(2)如果数字等于target,将该数加入答案ret,并结束遍历,将ret进行返回。(3)如果数字小于target,进行递归的调用,传入的数组和(target-该数)。剪枝操作:传入的数组从该数的位置往后数组,即不需要在考虑前面的数组的中的数,因为前面的数组中的数一定已经在前面遍历的递归调用时使用过了。,将递归返回的答案进行遍历,里面的每个数组加入该数,组成解加入ret中。遍历结果返回ret,结束递归。
哈希表改造法
在这类需要保持在原数组的上的操作,额外的空间需求为O(1),将原数组的改变成的Hash表。
在此题中,首先进行一遍遍历,将数组的中小于等于的数的值改变为的大于这个数组长度的值,即一定不可能在数组的中的有位置的值。此时列表中没有负数了,可以使用负数作为标记位:即遍历数组,如果一个数n = abs(nums[i])在1到nums_len之间,将n所在的位置(nums[n-1])的数变为负数,表示该位置的数在数组中存在,然后遍历数组,第一个不为负数的位置+1,为我们所要的结果,如果都存在,结果为长度下一位数。
置换法
遍历数组,每个位置的数使用一个while循环,条件为:1<=nums[i]<=len(nums) and nums[i]!=nums[nums[i-1]],注:将每个数组存在正确位置的数组的数放到其正确的位置上,其循环结束后面关键条件!!:如果已经在nums[i]的数已经在正确位置上了要结束循环,如果这个位置的数和要交换的位置上的数相同,也要结束循环,这样可以避免死循环,然后遍历数组,找到不合适位置的数i+1!=nums[i],如果都存在,结果为长度的下一位。
贪心策略
局部最优,从数组列表为1个数排列为1,当每次加入一个数,将之前个数的数的排列组合拿出来,然后在每个组合的不同位置插入新的元素,形成新的排列加入列表。
回溯算法
相当于一共有n个坑,每个坑要填入不同的值,使用回溯办法进行排列,没次在一个位置填入一个数之后,使用递归的方法,在下一个位置从剩余的数(将填入的数与数组中该位置的数组的交互,那么该位置后面的数全部是未填入的数。)中选择要填入的数,继续下一个位置的递归。结束条件为所有位置的都填满,将该排列加入答案,然后return。结束递归后,进行回溯,将排列中的数进行出栈,数组交互位置的数再交互换来,在下一个数填入该位置,开始新一轮的遍历。
贪心策略
与上面相同,最后加上去重,或者在加入时就判断是否重复来考虑是否加入。
回溯+剪枝
在进行遍历时,判断元素是否在这一层已经加入过,如果加入过,不再调用递归。即重复的元素只能出现在数的不同层,不能在数的同一层出现。
模拟法+矩阵标记
矩阵标记:每次走过的位置的元素,将该位置的元素的值设置为一个特殊值,表示该元素已经走过,如果下一个位置为走过的位置则改变方向。
首先建立移动方向的数组,direct = [[0,1],[1,0],[0,-1],[-1,0]],每次数组的下一个矩阵元素的位置为当前的位置加上的对应的direct的值,如果下一个位置符合条件,将该元素加入答案数组,并修改为特殊值,标志已经走过。否则改变方向(i = (i+1)%4),其中i表示的是direct矩阵中的方向。
代码
public int numDistinct(String s, String t){
int ret;
int n = s.length()+1;
int m = t.length()+1;
int[][] dp = new int[m][n];
dp[0][0] = 1;
for(int i=0;i<m;i++){
for(int j=1;j<n;j++){
if(i==0){dp[i][j]=1;}
else{
char si = t.charAt(i-1);
char tj = s.charAt(j-1);
if(tj == si){
dp[i][j] = dp[i][j-1] + dp[i-1][j-1];
}
else {
dp[i][j] = dp[i][j-1];
}
}
}
}
return dp[m-1][n-1];
}
public Node connect(Node root){
// 层次遍历
ArrayList<Node> a = new ArrayList<>();
a.add(root);
int start = 0;
int end = 0;
int nextEnd = 0;
while(start<=end){
Node temp = a.get(start);
if(temp.left!=null){
a.add(temp.left);
a.add(temp.right);
}
nextEnd =Math.max(nextEnd,a.size()-1);
if(start == end){
end = nextEnd;
start++;
}
else{
Node nextTemp = a.get(start+1);
temp.next = nextTemp;
start++;
}
}
return root;
}
// 使用next+递归的方式完成
public Node dfs(Node root){
if(root==null){
return root;
}
if(root.left!=null)
{
root.left.next = root.right;
if(root.next!=null){
root.right.next = root.next.left;
}
dfs(root.left);
dfs(root.right);
}
return root ;
}
public static void main(String[] args){
Solution sl = new Solution();
}
// 使用层次遍历的方法实现
public Node connect(Node root){
if(root==null)
return root;
Queue<Node> queue = new LinkedList<>();
queue.offer(root);
while(!queue.isEmpty()){
int n = queue.size();
Node last = null;
for(int i =0;i<n;i++)
{
Node temp = queue.poll();
if(temp.left!=null)
queue.offer(temp.left);
if(temp.right!=null)
queue.offer(temp.right);
if(i!=0)
last.next = temp;
last = temp;
}
}
return root;
}
public List<List<Integer>> generate(int numRows){
List<List<Integer>> ret = new ArrayList<List<Integer>>();
if(numRows==0)
return ret;
for(int i =0;i<numRows;i++){
List<Integer> temp = new ArrayList<>();
for(int j=0;j<=i;j++)
{
if(j==0||j==i){
temp.add(1);
}
else{
temp.add((ret.get(i-1).get(j-1)+ret.get(i-1).get(j)));
}
}
ret.add(temp);
}
return ret;
}
public List<Integer> getRow(int rowIndex) {
List<Integer> ret = new ArrayList<>();
for(int i=0;i<=rowIndex;i++){
int tempNum = 1;
for (int j=1;j<i;j++){
int next = tempNum+ret.get(j);
tempNum = ret.get(j);
ret.set(j,next);
}
ret.add(1);
}
return ret;
}
public int minimumTotal(List<List<Integer>> triangle) {
int n = triangle.size();
for(int i=1;i<n;i++) {
List<Integer> temp = triangle.get(i);
for(int j=0;j<=i;j++){
if(j==0){
int _temp = triangle.get(i-1).get(j)+temp.get(j);
temp.set(j,_temp);
}
else if(j==i){
int _temp = triangle.get(i-1).get(j-1)+temp.get(j);
temp.set(j,_temp);
}
else{
int _temp = Math.min(triangle.get(i-1).get(j),triangle.get(i-1).get(j-1))+temp.get(j);
temp.set(j,_temp);
}
}
triangle.set(i,temp);
}
int ret = 0x3f3f3f3f;
for(int j=0;j<=n-1;j++){
ret = Math.min(triangle.get(n-1).get(j),ret);
}
return ret;
}
public int maxProfit(int[] prices) {
int n = prices.length;
int ans = 0;
int buyPrice = prices[0];
for(int i=0;i<n;i++){
if(prices[i]>buyPrice ){
ans = Math.max(prices[i] - buyPrice,ans);
}
else{
buyPrice = prices[i];
}
}
return ans;
}
动态规划
贪心算法
一次遍历
public int maxProfit(int[] prices) {
int n = prices.length;
int ans = 0;
int buyPrice = prices[0];
for(int i=1;i<n;i++){
if(prices[i]<prices[i-1] ){
ans += prices[i-1]-buyPrice;
buyPrice = prices[i];
}
}
if(prices[n-1]>buyPrice){
ans += prices[n-1]-buyPrice;
}
return ans;
}
public int maxProfit(int[] prices) {
int n = prices.length;
int sell1 = 0,buy1 = -prices[0],sell2 = 0,buy2 = -prices[0];
for(int i =1;i<n;i++){
buy1 = Math.max(-prices[i],buy1);
sell1 = Math.max(buy1+prices[i],sell1);
buy2 = Math.max(buy2,sell1-prices[i]);
sell2 = Math.max(sell2,buy2+prices[i]);
}
return sell2;
}
private int maxSum = Integer.MIN_VALUE;
public int dfs(TreeNode root){
if(root == null)
return 0;
int leftVal = dfs(root.left);
int rightVal = dfs(root.right);
maxSum = Math.max(maxSum,leftVal+rightVal+root.val);
return root.val+Math.max(leftVal,rightVal);
}
public int maxPathSum(TreeNode root) {
dfs(root);
return maxSum;
}
}
class Solution {
public boolean isPalindrome(String s) {
int right = s.length()-1;
int left = 0;
while(left<right){
while(left<right && !Character.isLetterOrDigit(s.charAt(left))) left++;
while (left<right && !Character.isLetterOrDigit(s.charAt(right))) right--;
if(Character.toLowerCase(s.charAt(left)) != Character.toLowerCase(s.charAt(right))){
return false;
}
left++;
right--;
}
return true;
}
}
public List<List<String>> findLadders(String beginWord, String endWord, List<String> wordList) {
List<List<String>> res = new ArrayList<>();
Set<String> wordDict= new HashSet<>(wordList);
// 如果不含结束单词直接退出
if(!wordDict.contains(endWord)){
return res;
}
wordDict.remove(beginWord);
Map<String,Integer> steps = new HashMap<>();
steps.put(beginWord,0);
Map<String,List<String>> from = new HashMap<>();
int step = 1;
boolean found = false;
int wordLen = beginWord.length();
Queue<String> queue = new LinkedList<>();
queue.offer(beginWord);
while(!queue.isEmpty()){
int size = queue.size();
for(int i = 0;i<size;i++){
String curWord = queue.poll();
char[] charWord = curWord.toCharArray();
for(int j = 0;j<wordLen;j++){
char origin = charWord[j];
for(char c= 'a';c<='z';c++){
charWord[j] = c;
String newWord = String.valueOf(charWord);
if(steps.containsKey(newWord) && step== steps.get(newWord)){
from.get(newWord).add(curWord);
}
if(!wordDict.contains(newWord)){
continue;
}
wordDict.remove(newWord);
queue.offer(newWord);
from.putIfAbsent(newWord,new ArrayList<>());
from.get(newWord).add(curWord);
steps.put(newWord,step);
if(newWord.equals(endWord)){
found = true;
}
}
charWord[j] = origin;
}
}
step++;
if(found){
break;
}
}
if(found){
Deque<String> path = new ArrayDeque();
path.add(endWord);
dfs(from,path,beginWord,endWord,res);
}
return res;
}
public void dfs(Map<String,List<String>> from,Deque<String> path,String beginWord,String endWord, List<List<String>> res){
if(endWord.equals(beginWord)){
res.add(new ArrayList<>(path));
return;
}
else{
for(String s:from.get(endWord)){
path.addFirst(s);
dfs(from,path,beginWord,s,res);
path.removeFirst();
}
}
}
public int ladderLength(String beginWord, String endWord, List<String> wordList) {
Set<String> wordDict = new HashSet<>(wordList);
if(!wordDict.contains(endWord)){
return 0;
}
wordDict.remove(beginWord);
int currentStep = 0;
Queue<String> queue = new LinkedList<>();
wordDict.remove(beginWord);
queue.add(beginWord);
int wordLen = beginWord.length();
while(!queue.isEmpty()){
currentStep+=1;
int n = queue.size();
for(int i =0;i<n;i++){
String currentWord = queue.poll();
char[] charList = currentWord.toCharArray();
for(int j=0;j<wordLen;j++){
char origin = charList[j];
for(char c ='a';c<='z';c++){
charList[j] = c;
String newWord = String.valueOf(charList);
if(!wordDict.contains(newWord)){
continue;
}
wordDict.remove(newWord);
queue.add(newWord);
if(newWord.equals(endWord)){
return currentStep+1;
}
}
charList[j] = origin;
}
}
}
return 0;
}
public int longestConsecutive(int[] nums) {
int res = 0;
Set<Integer> intSet = new HashSet<>();
for(int num:nums){
intSet.add(num);
}
for(int num:nums){
if(!intSet.contains(num-1)){
int count = 1;
int temp = num+1;
while(intSet.contains(temp)){
temp++;
count++;
}
res = Math.max(res,count);
}
}
return res;
}
public int sumNumbers(TreeNode root) {
return dfs(root,0);
}
public int dfs(TreeNode root,int sum){
if(root==null){
return 0;
}
if(root.left==null && root.right==null){
return sum*10+root.val;
}
return dfs(root.left,sum*10+root.val)+dfs(root.right,sum*10+root.val);
}
public void solve(char[][] board) {
int m = board.length;
if(m==0)
return ;
int n = board[0].length;
for(int i=0;i<m;i++)
for(int j=0;j<n;j++){
if((i==0||i==m-1||j==0||j==n-1)&&board[i][j]=='O'){
dfs(board,i,j,m,n);
}
}
for(int i=0;i<m;i++)
for(int j=0;j<n;j++){
if(board[i][j]=='A'){
board[i][j]='O';
}
else {
board[i][j] = 'X';
}
}
}
public void dfs(char[][] board,int col ,int row,int m,int n){
if(col<0||col==m||row<0||row==n||board[col][row]=='X'||board[col][row]=='A'){
return;
}
board[col][row]='A';
dfs(board,col+1,row,m,n);
dfs(board,col-1,row,m,n);
dfs(board,col,row+1,m,n);
dfs(board,col,row-1,m,n);
}
List<List<String>> res = new ArrayList<>();
List<String> ans = new ArrayList<>();
boolean[][] dp;
int m;
public void dfs(String s,int i){
if(i==m){
res.add(new ArrayList<>(ans));
return ;
}
for(int j =i;j<m;j++){
if(dp[i][j]){
ans.add(s.substring(i,j+1));
dfs(s,j+1);
ans.remove(ans.size()-1);
}
}
}
public List<List<String>> partition(String s) {
// 动态规划
m = s.length();
if(m==0){
return new ArrayList<List<String>>();
}
dp = new boolean[m][m];
// 动态规划,标记所有的回文字符串的真伪
for(int i =m-1;i>=0;i--)
for(int j=i;j<m;j++){
if(i==j){
dp[i][j]= true;
}
else{
if(s.charAt(i)==s.charAt(j)){
if(j-i==1){
dp[i][j]=true;
}
else{
dp[i][j] = dp[i+1][j-1];
}
}
}
}
// 使用回溯的方法将所有的结果存储下来
dfs(s,0);
return res;
}
public int minCut(String s) {
int n = s.length();
boolean[][] dp = new boolean[n][n];
// 动态规划验证字符串是否为回文字符串
for(int i=n-1;i>=0;i--)
for(int j = i;j<n;j++){
if(i==j){
dp[i][j] = true;
}
else{
if(s.charAt(i)==s.charAt(j)){
if(j-i==1){
dp[i][j] = true;
}
else{
dp[i][j] = dp[i+1][j-1];
}
}
}
}
int[] f = new int[n];
for(int i=0;i<n;i++){
if(dp[0][i]){
f[i] = 0;
}
else{
f[i] = Integer.MAX_VALUE;
for(int j=i;j>=0;j--){
if(dp[j][i])
f[i] = Math.min(f[i],f[j-1]+1);
}
}
}
return f[n-1];
}
public Node cloneGraph(Node node) {
if(node==null)
return null;
return dfs(node);
}
public Node dfs(Node node){
if(nodeMap.containsKey(node.val))
return nodeMap.get(node.val);
Node newNode = new Node(node.val,new ArrayList<>());
nodeMap.put(newNode.val,newNode);
for(Node neighborNode: node.neighbors){
newNode.neighbors.add(dfs(neighborNode));
}
return newNode;
}
Map<Integer,Node> nodeMap = new HashMap<>();
public Node cloneGraph(Node node) {
if(node==null)
return null;
Node newNode = new Node(node.val,new ArrayList<>());
nodeMap.put(newNode.val,newNode);
Deque<Node> deque = new LinkedList<>();
deque.offer(node);
while(!deque.isEmpty()){
Node tempNode = deque.poll();
for(Node n:tempNode.neighbors){
if(nodeMap.containsKey(n.val)){
nodeMap.get(tempNode.val).neighbors.add(nodeMap.get(n.val));
}
else{
Node nextNode = new Node(n.val,new ArrayList<>());
nodeMap.put(nextNode.val,nextNode);
nodeMap.get(tempNode.val).neighbors.add(nextNode);
deque.offer(n);
}
}
}
return newNode;
}
一次遍历的方法
public int canCompleteCircuit2(int[] gas, int[] cost){
int n = gas.length;
int i = 0;
while(i<n){
int sumGas = 0,sumCost = 0;
int cnt = 0;
while(cnt<n){
sumGas += gas[cnt+i];
sumCost += cost[cnt+i];
if(sumCost>sumGas)
break;
}
if(cnt==n){
return i;
}
i = i+cnt;
}
return -1;
}
移动最低点的方法
public int canCompleteCircuit(int[] gas, int[] cost) {
int n = gas.length;
int minIndex = 0;
int minGas = Integer.MAX_VALUE;
int currentgas = 0;
for(int i=0;i<n;i++){
currentgas = gas[i]-cost[i];
if(currentgas<minGas){
minGas = currentgas;
minIndex = i;
}
}
return currentgas>=0?minIndex+1:-1;
}
public int candy(int[] ratings) {
// 贪心算法
int n = ratings.length;
int[] res = new int[n];
for(int i =0;i<n;i++){
res[i] = 1;
}
for(int i =1;i<n;i++){
if(ratings[i]>ratings[i-1]){
res[i] = res[i-1]+1;
}
}
int sum = res[n-1];
for(int i = n-2;i>=0;i--){
if(ratings[i]>ratings[i+1]&& res[i]<=res[i+1]){
res[i] = res[i+1]+1;
}
sum+=res[i];
}
return sum;
}
public int singleNumber(int[] nums) {
int res = 0 ;
int n = nums.length;
for(int i = 0;i<n;i++){
res^= nums[i];
}
return res;
}
public int singleNumber(int[] nums) {
Map<Integer,Integer> res = new HashMap<>();
int n = nums.length;
for(int i = 0;i<n;i++){
res.put(nums[i],res.getOrDefault(nums[i],0)+1);
}
int ret =0 ;
for(Map.Entry<Integer,Integer> entry:res.entrySet()){
if(entry.getValue()==1){
ret = entry.getKey();
}
}
return ret;
}
HashMap<Node,Node> map = new HashMap<>();
public Node copyRandomList(Node head) {
if(head==null){
return head;
}
return dfs(head);
}
public Node dfs(Node p){
Node temp = new Node(p.val);
map.put(p,temp);
if(p.next!=null ){
if(!map.containsKey(p.next))
temp.next = dfs(p.next);
else{
temp.next = map.get(p.next);
}
}
if(p.random!=null ){
if(!map.containsKey(p.random))
temp.random = dfs(p.random);
else{
temp.random = map.get(p.random);
}
}
return temp;
}
public boolean wordBreak(String s, List<String> wordDict) {
Set<String> wordSet = new HashSet<>(wordDict);
int n = s.length();
boolean[] dp = new boolean[n+1];
dp[0] = true;
for(int i = 0;i<n;i++){
for(int j = i;j>=0;j--){
String temp = s.substring(j,i+1);
if(wordSet.contains(temp) && dp[j]){
dp[i+1] = true;
break;
}
}
}
return dp[n];
}
List<String> ans = new ArrayList<>();
public List<String> wordBreak(String s, List<String> wordDict) {
Set<String> wordSet = new HashSet<>(wordDict);
List<String> ret = new ArrayList<>();
int n = s.length();
return ans;
}
public void dfs(int start,int n,String s, List<String> ret, Set<String> wordSet){
if(start==n){
ans.add(String.join(" ",ret));
return;
}
for(int i = start;i<n;i++){
String temp = s.substring(start,i+1);
if(wordSet.contains(temp)){
ret.add(temp);
dfs(i+1,n,s,ret,wordSet);
}
}
}
public boolean hasCycle(ListNode head) {
if(head==null){
return false;
}
ListNode p = head,q =head;
while(p!=null && q!=null){
p = p.next;
if(q.next==null)
return false;
q = q.next.next;
if(p==q)
return true;
}
return false;
}
public ListNode detectCycle(ListNode head) {
HashSet<ListNode> set = new HashSet<>();
ListNode p = head;
while(p!=null){
if(set.contains(p)){
return p;
}
set.add(p);
p = p.next;
}
return null;
}
public ListNode detectCycle(ListNode head) {
HashSet<ListNode> set = new HashSet<>();
ListNode p = head;
while(p!=null){
if(set.contains(p)){
return p;
}
set.add(p);
p = p.next;
}
return null;
}
List<Integer> ret = new ArrayList<>();
public List<Integer> preorderTraversal(TreeNode root) {
if(root== null)
return ret;
ret.add(root.val);
preorderTraversal(root.left);
preorderTraversal(root.right);
return ret;
}
List<Integer> ret = new ArrayList<>();
public List<Integer> postorderTraversal(TreeNode root) {
if(root== null)
return ret;
postorderTraversal(root.left);
postorderTraversal(root.right);
ret.add(root.val);
return ret;
}
public class LRUCache {
class DlinkNode{
int key;
int val;
DlinkNode prev;
DlinkNode next;
public DlinkNode(){}
public DlinkNode(int key,int val){
this.key = key;
this.val = val;
}
}
private int size;
private int capacity;
private DlinkNode head,tail;
private Map<Integer,DlinkNode> cache= new HashMap<>();
public LRUCache(int capacity){
this.size = 0;
this.capacity = capacity;
head = new DlinkNode();
tail = new DlinkNode();
head.next = tail;
tail.prev =head;
}
public int get(int key){
DlinkNode node = cache.get(key);
if(node==null){
return -1;
}
removeToHead(node);
return node.val;
}
public void removeToHead(DlinkNode node){
node.prev.next = node.next;
node.next.prev = node.prev;
node.prev = head;
node.next =head.next;
head.next.prev = node;
head.next = node;
}
public void put(int key,int val){
DlinkNode node = cache.get(key);
if(node==null){
node = new DlinkNode(key,val);
cache.put(key,node);
node.prev = head;
node.next = head.next;
head.next.prev = node;
head.next = node;
size++;
if(size>capacity){
delTail();
}
System.out.println(node.val);
}
else{
node.val = val;
removeToHead(node);
}
}
public void delTail(){
int key = tail.prev.key;
tail.prev =tail.prev.prev;
tail.prev.next = tail;
cache.remove(key);
--size;
}
}
public ListNode insertionSortList(ListNode head) {
ListNode pre = new ListNode();
pre.next = head;
if(head==null)
return head;
ListNode cur = head.next;
ListNode lastNode = head;
while(cur!=null){
ListNode q = pre;
while(q.next.val<cur.val){
q = q.next;
}
if(q == lastNode){
lastNode = cur;
cur = cur.next;
}
else{
lastNode.next = cur.next;
cur.next = q.next;
q.next = cur;
cur = lastNode.next;
}
}
return pre.next;
}
public ListNode sortList(ListNode head) {
// 自定向下的归并排序
if(head==null || head.next==null)
return head;
ListNode pre = new ListNode();
pre.next = head;
ListNode slow = head,fast = head;
while(fast.next!=null && fast.next.next!=null){
fast = fast.next.next;
slow = slow.next;
}
ListNode tmp = slow.next;
slow.next = null;
ListNode left = sortList(head);
ListNode right = sortList(tmp);
ListNode p = pre;
while(left!=null && right!=null){
if(left.val<right.val){
p.next = left;
left = left.next;
}
else{
p.next = right;
right = right.next;
}
p = p.next;
}
if(left!=null)
p.next = left;
else{
p.next = right;
}
return pre.next;
}
public int evalRPN(String[] tokens) {
Stack<String> stack = new Stack<>();
for(String s:tokens){
if(!s.equals("+") && !s.equals("-") &&!s.equals("*")&& !s.equals("/"))
stack.push(s);
else{
int num1,num2;
switch (s){
case "+":
num1 = Integer.parseInt(stack.pop());
num2 = Integer.parseInt(stack.pop());
stack.push(String.valueOf(num1+num2));
break;
case "-":
num1 = Integer.parseInt(stack.pop());
num2 = Integer.parseInt(stack.pop());
stack.push(String.valueOf(num2-num1));
break;
case "*":
num1 = Integer.parseInt(stack.pop());
num2 = Integer.parseInt(stack.pop());
stack.push(String.valueOf(num1*num2));
break;
case "/":
num1 = Integer.parseInt(stack.pop());
num2 = Integer.parseInt(stack.pop());
stack.push(String.valueOf(num2/num1));
break;
}
System.out.println(s);
}
}
return Integer.parseInt(stack.pop());
}
使用语言特性
public String reverseWords(String s) {
s.trim(); // 去除两端的空格
List<String> wordList = Arrays.asList(s.split("\\s+")); // 分割字符串构建成的集合
Collections.reverse(wordList);
return String.join(" ",wordList);
}
双端队列+StringBuffer
public String reverseWords(String s) {
Deque<String> d = new ArrayDeque<>();
int left =0,right = s.length()-1;
while (left<=right && s.charAt(left)==' '){
left++;
}
while (left<=right && s.charAt(right)==' '){
right--;
}
StringBuffer word = new StringBuffer();
while(left<=right){
char c = s.charAt(left);
if((word.length()!=0)&&c==' '){
d.offerFirst(word.toString());
word.setLength(0);
}
else if(c !=' '){
word.append(c);
}
left++;
}
if(word.length()!=0){
d.offerFirst(word.toString());
}
return String.join(" ",d);
}
public int maxProduct(int[] nums) {
// 动态规划
int f = nums[0];
int g = nums[0];
int n = nums.length;
int ret = nums[0];
for(int i = 1;i<n;i++){
int tmp = f;
f = Math.max(f*nums[i],g*nums[i]);
f = Math.max(f,nums[i]);
g = Math.min(tmp*nums[i],g*nums[i]);
g = Math.min(g,nums[i]);
ret = Math.max(f,ret);
}
return ret;
}
public int findMin(int[] nums) {
// 二分查找
int n = nums.length;
int left = 0,right = n-1;
while(left<right){
int mid = (left+right)/2;
if(nums[right]>nums[mid]){
right = mid;
}
else {
left = mid+1;
}
}
return nums[left];
}
public int findMin(int[] nums) {
int left = 0,right = nums.length-1;
while(left<right){
int mid = (left+right)/2;
if(nums[mid]<nums[right]){
right = mid;
}
else{
if(nums[right]<nums[mid]){
left = mid+1;
}
else{
right--;
}
}
}
return nums[left];
}
class MinStack {
/** initialize your data structure here. */
private Stack<Integer> s= new Stack<>();
public MinStack() {
}
public void push(int val) {
s.add(val);
}
public void pop() {
s.pop();
}
public int top() {
return s.peek();
}
public int getMin() {
int ret = Integer.MAX_VALUE;
for(int i:s){
if(i<ret)
ret = i;
}
return ret;
}
}
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
HashSet<ListNode> set = new HashSet<>();
ListNode p = headA;
ListNode q = headB;
while(p!=null || q!=null){
if(p!=null){
if(set.contains(p)){
return p;
}
set.add(p);
p = p.next;
}
if(q!=null){
if(set.contains(q)){
return q;
}
set.add(q);
q = q.next;
}
}
return q;
}
public int findPeakElement(int[] nums) {
int right = nums.length-1;
int left = 0;
while(left<right){
int mid = (left+right)/2;
if(nums[mid]>nums[mid+1]){
right = mid;
}
else
{
left = mid+1;
}
}
return left;
}
public int maximumGap(int[] nums) {
int n = nums.length;
int[] cp = new int[n];
int maxValue = Arrays.stream(nums).max().getAsInt();
int e = 1;
while(maxValue>=e){
int[] cnt = new int[10];
for(int i =0;i<n;i++){
int digit = (nums[i]/e)%10;
cnt[digit]++;
}
for(int i =1;i<10;i++){
cnt[i] += cnt[i-1];
}
for(int i =n-1;i>=0;i--){
int digit = (nums[i]/e)%10;
cp[cnt[digit]-1] = nums[i];
cnt[digit]--;
}
e*= 10;
System.arraycopy(cp,0,nums,0,n);
}
int ret = 0;
for(int i =1;i<n;i++){
ret = Math.max(ret,nums[i]-nums[i-1]);
}
return ret;
}