- 不同路径
当前路径数取决于我的上一个和前一个,我要的就是更新后的数据,所以从前往后
java
class Solution {
public int uniquePaths(int m, int n) {
int[] dp=new int[n];
Arrays.fill(dp,1);
for(int i=1;i<m;i++){
for(int j=1;j<n;j++){
dp[j]+=dp[j-1];
}
}
return dp[n-1];
}
}
- 最小路径和
java
class Solution {
public int minPathSum(int[][] grid) {
int m=grid.length,n=grid[0].length;
int[] dp=new int[n];
dp[0]=grid[0][0];
for(int i=1;i<n;i++) dp[i]=dp[i-1]+grid[0][i];
for(int i=1;i<m;i++){
dp[0]=dp[0]+grid[i][0];
for(int j=1;j<n;j++){
dp[j]=Math.min(dp[j],dp[j-1])+grid[i][j];
}
}
return dp[n-1];
}
}
- 最长回文子串
这道题很low,就是回文分割那题的预处理
java
class Solution {
public String longestPalindrome(String s) {
int l=0,r=0,n=s.length();
boolean[][] dp=new boolean[n+1][n+1];
for(int i=1;i<=n;i++) Arrays.fill(dp[i],true);
for(int i=1;i<=n;i++){
for(int j=i-1;j>=1;j--){
if(s.charAt(i-1)==s.charAt(j-1)&&dp[i-1][j+1]){
dp[i][j]=true;
if(r-l-1<i-j-1){
r=i;
l=j;
}
}
else dp[i][j]=false;
}
}
return s.substring(l,r+1);
}
}
当然可以采用中心扩展法
面试优先写
java
class Solution {
int start,end;
public String longestPalindrome(String s) {
for(int i=1;i<s.length();i++){
check(s,i-1,i-1);
check(s,i-1,i);
}
return s.substring(start,end+1);
}
public void check(String s,int l,int r){
while(l>=0&&r<s.length()&&s.charAt(l)==s.charAt(r)){
l--;
r++;
}
if(r-l-2>end-start){
start=l+1;
end=r-1;
}
}
}
- 最长公共子序列
dp[i][j]表示第一个字符前i个,和第二个字符前j个对最长公共子序列
java
class Solution {
public int longestCommonSubsequence(String text1, String text2) {
int n1=text1.length(),n2=text2.length();
int[][] dp=new int[n1+1][n2+1];
for(int i=1;i<=n1;i++){
for(int j=1;j<=n2;j++){
if(text1.charAt(i-1)==text2.charAt(j-1)) dp[i][j]=dp[i-1][j-1]+1;
else dp[i][j]=Math.max(dp[i-1][j],dp[i][j-1]);
}
}
return dp[n1][n2];
}
}
- 编辑距离
和上道题一样
就是注意,对于一个为零另一个为数时,dp[0][i]=i(初始化)
java
class Solution {
public int minDistance(String word1, String word2) {
int n1=word1.length(),n2=word2.length();
int[][] dp=new int[n1+1][n2+1];
for(int i=1;i<=n1;i++) dp[i][0]=i;
for(int i=1;i<=n2;i++) dp[0][i]=i;
for(int i=1;i<=n1;i++){
for(int j=1;j<=n2;j++){
if(word1.charAt(i-1)==word2.charAt(j-1)) dp[i][j]=dp[i-1][j-1];
else{
dp[i][j]=Math.min(Math.min(dp[i][j-1],dp[i-1][j]),dp[i-1][j-1])+1;
}
}
}
return dp[n1][n2];
}
}
- 出现一次的数字
异或
java
class Solution {
public int singleNumber(int[] nums) {
int res=0;
for(int i=0;i<nums.length;i++){
res^=nums[i];
}
return res;
}
}
- 多数元素
不同元素相互抵消
java
class Solution {
public int majorityElement(int[] nums) {
int num=nums[0],count=1;
for(int i=1;i<nums.length;i++){
if(count==0){
num=nums[i];
count++;
}
else{
if(nums[i]==num) count++;
else count--;
}
}
return num;
}
}
- 颜色分类
注意结束条件是i<=r否则2和1又交换了
while里面也要控制r>=i防止改变之前已经合理的序列
java
class Solution {
public void sortColors(int[] nums) {
int l=0,r=nums.length-1;
for(int i=0;i<=r;i++){
while(r>=i&&nums[i]==2){
swap(nums,i,r);
r--;
}
if(nums[i]==0){
swap(nums,i,l);
l++;
}
}
}
public void swap(int[] nums,int first,int second){
int temp=nums[first];
nums[first]=nums[second];
nums[second]=temp;
}
}
- 下一个排列
其实就是找到大于当前值的最小值
从后往前找到第一个不递增的数,然后从后往前找到第一个大于他的数,保证了这次的值是大于上次值,但是不能保证是最小的,通过将后面的值reverse后,就得到了最小值
java
class Solution {
public void nextPermutation(int[] nums) {
int i=nums.length-2;
for(;i>=0;i--){
if(nums[i]<nums[i+1]) break;
}
if(i>=0){
int j=nums.length-1;
for(;j>=0;j--){
if(nums[i]<nums[j]) break;
}
swap(nums,i,j);
}
reverse(nums,i+1,nums.length-1);
}
public void swap(int[] nums,int first,int second){
int temp=nums[first];
nums[first]=nums[second];
nums[second]=temp;
}
public void reverse(int[] nums,int l,int r){
while(r>l){
swap(nums,r,l);
r--;
l++;
}
}
}
- 寻找重复数
快慢指针判断是否有环
注意:最后值就是fast
java
class Solution {
public int findDuplicate(int[] nums) {
int slow=0,fast=0;
do{
fast=nums[nums[fast]];
slow=nums[slow];
}while(fast!=slow);
fast=0;
while(fast!=slow){
fast=nums[fast];
slow=nums[slow];
}
return nums[fast];
}
}