腾讯2017实习生编程题之构造回文

思路:一开始看起来没有思绪,但是仔细想想,这个问题可以转换为两个字符串求公共子序列

         注意一个概念上的差异,公共子序列和公共子串。前者不要求连续,后者要求连续。

         这个问题可以转换为字符串和其reverse之后的字符串求最大子序列

        那么,怎么求最大子序列,考虑动态规划解决这个问题。

        假设Xi=<x1,x2,……,xi>,Yj=<y1,y2,……,yj>为两个序列,用矩阵c[i,j]来记录公共子序列的个数

        如果xi=yj,则c[i,j]=c[i-1,j-1]+1

        如果xi不等于yj,则c[i,j]=max{c[i-1,j],max[i,j-1]}

        结束条件:I或j为0,则c[i,j]=0

代码:

import java.util.*;

public class Main{
 
    public static void main(String[] args){
        Scanner sc=new Scanner(System.in);
        while(sc.hasNextLine()){
            String line=sc.nextLine();
            calculate(line);
        }
    }

 private static void calculate(String str) {
  StringBuilder sb=new StringBuilder();
  for(int k=str.length()-1;k>=0;k--){
   sb.append(str.charAt(k));
  }
  String reverseStr=sb.toString();

  
  int[][] matrix=new int[reverseStr.length()+1][str.length()+1];
  String[][] flag=new String[reverseStr.length()+1][str.length()+1];
  
  for(int x=0;x<=str.length();x++){
   matrix[0][x]=0;
   
  }
  
  for(int y=0;y<=reverseStr.length();y++){
   matrix[y][0]=0;
   
  }
  
  
  for(int i=1;i<=reverseStr.length();i++){
   for(int j=1;j<=str.length();j++){
    if(reverseStr.charAt(i-1)==str.charAt(j-1)){
     matrix[i][j]=matrix[i-1][j-1]+1;
    }else{
     if(matrix[i-1][j]>matrix[i][j-1]){
      matrix[i][j]=matrix[i-1][j];
     }else{
      matrix[i][j]=matrix[i][j-1];
     }
    }
   }
    
  }
  
  
  System.out.println(str.length()-matrix[reverseStr.length()][str.length()]);
  
 }

如果要打印出相同回文内容,则代码为:

import java.util.*;

public class Main{
 
    public static void main(String[] args){
        Scanner sc=new Scanner(System.in);
        while(sc.hasNextLine()){
            String line=sc.nextLine();
            calculate(line);
        }
    }

 private static void calculate(String str) {
  StringBuilder sb=new StringBuilder();
  for(int k=str.length()-1;k>=0;k--){
   sb.append(str.charAt(k));
  }
  String reverseStr=sb.toString();
  
  
  int[][] matrix=new int[reverseStr.length()+1][str.length()+1];
  String[][] flag=new String[reverseStr.length()+1][str.length()+1];
  
  for(int x=0;x<=str.length();x++){
   matrix[0][x]=0;
   
  }
  
  for(int y=0;y<=reverseStr.length();y++){
   matrix[y][0]=0;
   
  }
  
  
  for(int i=1;i<=reverseStr.length();i++){
   for(int j=1;j<=str.length();j++){
    if(reverseStr.charAt(i-1)==str.charAt(j-1)){
     matrix[i][j]=matrix[i-1][j-1]+1;
     flag[i][j]="left-up";
    }else{
     if(matrix[i-1][j]>matrix[i][j-1]){
      matrix[i][j]=matrix[i-1][j];
      flag[i][j]="up";
     }else{
      matrix[i][j]=matrix[i][j-1];
      flag[i][j]="left";
     }
    }
   }
    
  }
  
  
  System.out.println(str.length()-matrix[reverseStr.length()][str.length()]);
  LinkedList<Character> list=new LinkedList<>();
  sequence(str,flag,reverseStr.length(),str.length(),list);
  
 }

 private static void sequence(String str,String[][] flag,int i,int j,LinkedList<Character> list) {
  
  if(i==0||j==0){
   StringBuilder sb=new StringBuilder();
   for(Character current:list){
    sb.append(current);
   }
   
   System.out.println(sb.toString());
   return;
  }
  
  if(flag[i][j].equals("left-up")){
   list.addFirst(str.charAt(j-1));
   sequence(str,flag,i-1,j-1,list);
  }else if(flag[i][j].equals("up")){
   sequence(str,flag,i-1,j,list);
  }else{
   sequence(str,flag,i,j-1,list);
  }
 }
}

考虑了一下,求两个字符串的最长子串实际上可以通过类似的方法解决,只是这时候当xi=yj,c[i][j]=c[i-1][j-1]+1
当xi不等于yj时,c[i][j]=0.区别就在于子串要求连续,子序列不要求连续。

代码:
import java.util.*;

public class Main{
 public static void main(String[] args){
  Scanner sc=new Scanner(System.in);
  String line1=sc.nextLine();
  String line2=sc.nextLine();
  
  calculate(line1,line2);
 }
 
 private static void calculate(String str1,String str2){
  
  int[][] matrix=new int[str1.length()+1][str2.length()+1];
  
  for(int x=0;x<=str1.length();x++){
   matrix[x][0]=0;
  }
  
  for(int y=0;y<=str2.length();y++){
   matrix[0][y]=0;
  }
  int max=-1,x=0,y=0;
  for(int i=1;i<=str1.length();i++){
   for(int j=1;j<=str2.length();j++){
    if(str1.charAt(i-1)==str2.charAt(j-1)){
     matrix[i][j]=matrix[i-1][j-1]+1;
    }else{
     matrix[i][j]=0;
    }
    if(matrix[i][j]>max){
     max=matrix[i][j];
     x=i;
     y=j;
    }
   }
  }
  System.out.println(x+" "+y);
  LinkedList<Character> list=new LinkedList<>();
  
  subString(matrix,x,y,str1,list);
  
  
 }
 
 private static void subString(int[][] matrix,int i,int j,String str,LinkedList<Character> list){
  
  if(matrix[i][j]==0){
   StringBuilder sb=new StringBuilder();
   
   for(Character c:list){
    sb.append(c);
   }
   
   System.out.println(sb.toString());
   
   return;
  }
  
  list.addFirst(str.charAt(i-1));
  
  subString(matrix,i-1,j-1,str,list);
 }
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值