刷题3

青蛙跳台阶

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Solution {
public int numWays(int n) {
if(n==0)
return 1;
int[] array=new int[n+1];
array[0]=1;
array[1]=1;
for(int i=2;i<=n;i++)
{
array[i]=array[i-1]+array[i-2];
array[i]%=1000000007;
}
return array[n];
}
}

最长上升子序列

很容易想到O(n^2)的解法,可以定义一个数组保存当前位置为止的最长上升子序列

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
class Solution {
public int lengthOfLIS(int[] nums) {
if(nums.length==0)
return 0;
int[] array=new int[nums.length];
array[0]=1;
for(int i=1;i<nums.length;i++)
{
int max=1;
for(int j=0;j<i;j++)
{
if(nums[i]>nums[j])
{
max=Math.max(max,array[j]+1);
}
}
array[i]=max;
}
int max=0;
for(int i=0;i<array.length;i++)
{
if(max<array[i])
max=array[i];
}
return max;
}
}

最长公共子序列

这道题是一道典型的动态规划题

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class Solution {
public int longestCommonSubsequence(String text1, String text2) {
int length1=text1.length();
int length2=text2.length();
int[][] array=new int[length1+1][length2+1];
for(int i=0;i<length1;i++)
{
for(int j=0;j<length2;j++)
{
if(text1.charAt(i)==text2.charAt(j))
{
array[i+1][j+1]=array[i][j]+1;
}
else if(array[i+1][j]>array[i][j+1])
array[i+1][j+1]=array[i+1][j];
else
array[i+1][j+1]=array[i][j+1];
}
}
return array[length1][length2];

}
}

编辑距离

看了大佬的解答跪了,还是没有考虑完全,其实跟平常的动态规划题差别
不大,核心就是分析最优情况

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class Solution {
public int minDistance(String word1, String word2) {
int m=word1.length();
int n=word2.length();
int[][] cost=new int[m+1][n+1];
for (int i = 0; i <= m; ++i) {
cost[i][0] = i;
}
for (int j = 0; j <= n; ++j) {
cost[0][j] = j;
}
for (int i = 1; i <= m; ++i) {
for (int j = 1; j <= n; ++j) {
if (word1.charAt(i-1) == word2.charAt(j-1)) {
cost[i][j] = cost[i-1][j-1];
} else {
cost[i][j] = 1 +
Math.min(cost[i-1][j-1], Math.min(cost[i][j-1],
cost[i-1][j]));
}
}
}
return cost[m][n];
}
}

零钱兑换II

这题有点难度,官方题解还没看懂

1
2
3
4
5
6
7
8
9
10
11
12
13
class Solution {
public int change(int amount, int[] coins) {
int[] dp = new int[amount + 1];
dp[0] = 1;

for (int coin : coins) {
for (int x = coin; x < amount + 1; ++x) {
dp[x] += dp[x - coin];
}
}
return dp[amount];
}
}

翻转单词顺序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Solution {
public String reverseWords(String s) {
s=s.trim();
String[] array=s.split(" ");
StringBuilder str=new StringBuilder();
for(int i=array.length-1;i>=0;i--)
{
if(array[i].equals(""))
continue;
if(i!=0)
str.append(array[i]+" ");
else
str.append(array[i]);
}
return str.toString();

}
}

二进制中1的个数

这个题的n是无符号数,区分正负会有问题,最简明的思路是按位与,还有一种
思路是利用n&(n-1),n-1的意思是二进制数字n最右边的1变成0,此1右边的0
都变成1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public int hammingWeight(int n) {
int sum=0;
while(n!=0){
sum=sum+(n&1);
//无符号右移
n=n>>>1;
}
return sum;
}
public int hammingWeight(int n) {
int sum=0;
while(n!=0){
sum++;
//每次都消去一个1
n&=(n-1);
}
return sum;
}

颠倒二进制位

这道题的思路不难,我对位运算还是掌握不深,循环32次,每次将右边最后
1位获取保存,同时已经保存的位左移

1
2
3
4
5
6
7
8
9
10
11
public int reverseBits(int n) {
int res=0;
for(int i=0;i<32;i++)
{
//注意在获取最后一位之前必须确保之前的结果左移
res<<=1;
res=res|(n&1);
n>>>=1;
}
return res;
}

复制IP地址

回溯剪枝

1
2


两数之和

利用HashMap的特性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Solution {
public int[] twoSum(int[] nums, int target) {
//利用hashMap
HashMap<Integer,Integer> a=new HashMap<>();
for(int i=0;i<nums.length;i++)
{
if(a.containsKey(target-nums[i]))
return new int[]{a.get(target-nums[i]),i};
else
a.put(nums[i],i);
}
return null;
}
}

三数之和

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
List<List<Integer>> a=new ArrayList<>();
if(nums==null)
return a;
if(nums.length<3)
return a;
Arrays.sort(nums);
int start=0;
int end=nums.length-1;
for(int i=0;i<nums.length;i++)
{
if(nums[i]>0)
break;
if(i>0&&nums[i]==nums[i-1])
continue;
start=i+1;
end=nums.length-1;
while(start<end)
{
if(nums[i]+nums[start]+nums[end]==0)
{
ArrayList<Integer> b=new ArrayList<>();
b.add(nums[i]);
b.add(nums[start]);
b.add(nums[end]);
a.add(b);
while(start<end&&nums[start]==nums[start+1])
start++;
while(start<end&&nums[end]==nums[end-1])
end--;
start++;
end--;
}
else if(nums[i]+nums[start]+nums[end]>0)
end--;
else
start++;

}
}
return a;
}
}

最接近的三数之和

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
class Solution {
public int threeSumClosest(int[] nums, int target) {
int ans=nums[0]+nums[1]+nums[2];
Arrays.sort(nums);
boolean flag=false;
for(int i=0;i<nums.length;i++)
{
int start=i+1;
int end=nums.length-1;
if(flag==true)
break;
while(start<end)
{
if(Math.abs(nums[i]+nums[start]+nums[end]-target)<Math.abs(
ans-target))
ans=nums[i]+nums[start]+nums[end];
if(ans==target)
{
flag=true;
break;
}
if(nums[i]+nums[start]+nums[end]>target)
end--;
else
start++;
}

}
return ans;

}
}

买卖股票的最佳时机I

1
2
3
4
5
6
7
8
9
10
11
12
class Solution {
public int maxProfit(int[] prices) {
int num=0;
int profit=0;
for(int i=0;i<prices.length-1;i++)
{
num=Math.max(0,num+prices[i+1]-prices[i]);
profit=Math.max(num,profit);
}
return profit;
}
}

买股票的最佳时机II

这道题的条件其实很宽松,可以进行多次买卖,所以只关注眼前每次遇到更大
的就买卖,贪心算法

1
2
3
4
5
6
7
8
9
10
11
12
13
class Solution {
public int maxProfit(int[] prices) {
int sum=0;
for(int i=0;i<prices.length-1;i++)
{
if(prices[i]<prices[i+1])
{
sum=sum+prices[i+1]-prices[i];
}
}
return sum;
}
}

买股票的最佳时机III

动态规划

1
2


有效的括号

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
class Solution {
public boolean isValid(String s) {
int length=-1;
ArrayList<Character> list=new ArrayList<>();
for(int i=0;i<s.length();i++)
{
char ch=s.charAt(i);
if(ch=='('||ch=='{'||ch=='[')
{
list.add(ch);
length++;
}
else if(ch==')'||ch=='}'||ch==']')
{
if(length==-1)
return false;
char temp=list.get(length);
if((ch==')'&&temp=='(')||(ch=='}'&&
temp=='{')||(ch==']'&&temp=='['))
{
list.remove(length);
length--;
}
else
return false;
}
}
if(list.size()>0)
return false;
return true;
}
}

最长有效括号

动态规划

单词搜索

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
public class Solution {
private boolean[][] marked;
private int[][] direction = {{-1, 0}, {0, -1}, {0, 1}, {1, 0}};
// 盘面上有多少行
private int m;
// 盘面上有多少列
private int n;
private String word;
private char[][] board;

public boolean exist(char[][] board, String word) {
m = board.length;
if (m == 0) {
return false;
}
n = board[0].length;
marked = new boolean[m][n];
this.word = word;
this.board = board;

for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (dfs(i, j, 0)) {
return true;
}
}
}
return false;
}

private boolean dfs(int i, int j, int start) {
if (start == word.length() - 1) {
return board[i][j] == word.charAt(start);
}
if (board[i][j] == word.charAt(start)) {
marked[i][j] = true;
for (int k = 0; k < 4; k++) {
int newX = i + direction[k][0];
int newY = j + direction[k][1];
if (inArea(newX, newY) && !marked[newX][newY]) {
if (dfs(newX, newY, start + 1)) {
return true;
}
}
}
marked[i][j] = false;
}
return false;
}

private boolean inArea(int x, int y) {
return x >= 0 && x < m && y >= 0 && y < n;
}

public static void main(String[] args) {
char[][] board = {{'a', 'b'}};
String word = "ba";
Solution solution = new Solution();
boolean exist = solution.exist(board, word);
System.out.println(exist);
}
}

重排链表

快慢指针

验证栈序列

贪心算法

字典序排数

剪绳子I

贪心算法

剪绳子II

贪心算法

最长回文子串

这道题有点难度,容易想到的是中心扩散法,从某个位置向两边进行
扩散,但是要分两种情况,例如aba abba

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
class Solution {
public String longestPalindrome(String s) {
if(s.length()<2)
return s;
int maxlength=1;
int left=0;
int right=0;
String ss=s.substring(0,1);
for(int i=0;i<s.length()-1;i++)
{
String s1=Stringcut(s,i,i+1);
String s2=Stringcut(s,i,i);
String max=s1.length()>s2.length()?s1:s2;
if(max.length()>maxlength)
{
ss=max;
maxlength=max.length();
}
}
return ss;
}
public String Stringcut(String s,int left,int right)
{
int length=s.length();
int i=left;
int j=right;
while(i>=0&&j<length)
{
if(s.charAt(i)==s.charAt(j))
{
i--;
j++;
}
else
break;
}
return s.substring(i+1,j);
}
}

下一个数

位运算

Author: 高明
Link: https://skysea-gaoming.github.io/2020/11/09/LeetCodeandnowcoder3/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.