vivo2019秋招笔试真题 1.字符串排序 2.链表拆分 3.最长回文子串

1.字符串排序

【题目描述】请对组字符串进行排序,字符串由大小写字母和数字组成,需要满足以下比较规则:

  • 长度不同时,长度较短在排前面
  • 长度相同时,按照字典顺序排列(AaBb-Zz, 0-9顺序),即大写字母在小写字母前,数字排在字母后,要求时间复杂度为O(nlogn)。

比如:
“abc”,“Abc”,“123”,“1”,“1bc”,“CBD”,“abcd”,“a”
abc Abc 123 1bc CBD abed a
排序后结果为:
a 1 Abc abc CBD 1bc 123 abcd

解题思路:
将字符的顺序重新排列,实现cmp函数计算ASCII码值做相应的处理,处理后排序为(AaBb-Zz, 0-9顺序)

字符对应的ASCII码值:

字符ASCII码值字符ASCII码值字符ASCII码值
A-Z65-90a-z97-1220-948-57

需要处理过后的字符顺序:

字符处理后返回值字符处理后返回值字符处理后返回值字符处理后返回值
A0I16Q32Y48
a1i17q33y49
B2J18R34Z50
b3j19r35z51
C4K20S36052
c5k21s37153
D6L22T38254
d7l23t39355
E8M24U40456
e9m25u41557
F10N26V42658
f11n27v43759
G12O28W44860
g13o29w45961
H14P30X46
h15p31x47

解题代码:

public static void main(String[] args) {
        String[] input = {"abc", "Abc", "123", "1", "1bc", "CBD", "abcd", "a"};
        sort(input);
        for (String s:input){
            System.out.println(s);
        }
    }

    public static void sort(String []input){
        quickSort(input,0,input.length-1);
    }
	// 快排
    public static void quickSort(String []data,int left,int right){
        if (left>right){
            return;
        }
        int i;
        int j;
        String tmp=data[left];
        i=left;
        j=right;
        while (i!=j){
            // 从右至左开始找到j位置比tmp小的串
            while (cmp(data[j],tmp)>=0&&i<j){
                j--;
            }
            // 从左至右开始找到i位置比tmp大的串
            while (cmp(data[i],tmp)<=0&&i<j){
                i++;
            }
            if (i<j){
                String t;
                t=data[i];
                data[i]=data[j];
                data[j]=t;
            }
        }
        // i==j,将tmp放入适合的位置
        data[left]=data[i];
        data[i]=tmp;
        quickSort(data,left,i-1);
        quickSort(data,i+1,right);
    }

    public static int cmp(String left,String right){
        if (left.length()!=right.length()){
            return left.length()-right.length();
        }
        // 字符串长度相等的情况
        int len=left.length();
        for (int i=0;i<len;i++){
            char l=left.charAt(i);
            char r=right.charAt(i);
            // 直到两者中遍历到不同的字符
            if (l==r){
                continue;
            }
            // 获取字符的值
            int lcv=getCharValue(l);
            int rcv=getCharValue(r);
            if (lcv!=rcv){
                return lcv-rcv;
            }
        }
        // 相等
        return 0;
    }
    // A返回0,a返回1,B返回2,b返回3...
    public static int getCharValue(char c){
        // a-z
        if (c>='a'){
            return (c-'a')*2+1;
        // A-Z
        }else if (c>='A'){
            return (c-'A')*2;
        }
        // 如果c为数字
        return c-'0'+52;
    }

2.链表拆分(链表奇数位正序偶数位逆序)

【题目描述】设C={a1, b1, a2, b2…an, bn}为线性表,采用带头结点的hc单链表存放,设计一个算法,将其拆分为两个线性表,使得奇数位保持正序,偶数位转化为逆序。即:
A = {a1,a2…an}, B= {bn…b2,b1)

解题思路:
奇数使用尾插法,偶数使用头插法

解题代码:

// 思路:奇数使用尾插法,偶数使用头插法
    static class  ListNode {
        int val;
        ListNode next ;
        public ListNode(int val) {
            this.val = val;
        }
    }
    public static void main(String[] args) {
    	//测试用例链表
        ListNode head=new ListNode(1);
        head.next=new ListNode(2);
        head.next.next=new ListNode(3);
        head.next.next.next=new ListNode(4);
        head.next.next.next.next=new ListNode(5);
        head.next.next.next.next.next=new ListNode(6);
        head.next.next.next.next.next.next=new ListNode(7);
        System.out.print("原来的链表:");
        printListNode(head);
        System.out.println();
        oddEvenList(head);
    }


    public static void oddEvenList(ListNode node) {
        if (node == null) {
            return;
        }
        // 奇数  奇数,使用尾插法
        ListNode odd= new ListNode(-1);
        ListNode oddHead = odd;
        // 偶数
        ListNode evenHead = null;
        int i = 0;
        while (node != null){
            // 奇数,使用尾插法
            if((i+1) % 2 !=0){
                odd.next = node;
                node = node.next;
                odd = odd.next;
            }else{
                // 使用头插法,因为是逆序
                ListNode tmp=new ListNode(node.val);
                tmp.next=evenHead;
                evenHead=tmp;
                node = node.next;
            }
            i++;
        }
        // 处理
        oddHead=oddHead.next;
        odd.next=null;
        System.out.print("奇数链表:");
        printListNode(oddHead);
        System.out.println();
        System.out.print("偶数链表:");
        printListNode(evenHead);
    }
    // 打印结果
    private static void printListNode(ListNode node) {
        while (node!=null){
            System.out.print(node.val+" ");
            node = node.next;
        }
    }

结果:
在这里插入图片描述

3.最长对称子串(最长回文子串)

【题目描述】定义前后两端完全一致的字符串为对称字符串,如“abba”,“caddac”,编写程序,输出字符串"abcdefiiaaovivoovivcaideumncca"的最长对称子字符串。

解题思路:动态规划
设状态dp[j][i]表示索引j到索引i的子串是否是回文串。则转移方程为:
在这里插入图片描述则dp[j][i]为true时表示索引j到索引i形成的子串为回文子串,且子串起点索引为j,长度为i - j + 1。
算法时间复杂度为O(N ^ 2)。

解题代码:(这里置1来代表true)

	public String longestPalindrome(String s) {
		 if(s==null||s.length()<=0) return "";
		 int n=s.length();
		 int [][]dp=new int[n][n];
		 int start=0;
		 int max=1;
		 for(int i=0;i<n;i++) {
			 for(int j=0;j<=i;j++) {//注意小于等于i!!!  因为要构建dp[i][i]=1
				 if(j==i) {
					 dp[i][i]=1;
				 }else if(i-j==1&&s.charAt(i)==s.charAt(j)){
					 dp[j][i]=1;
				 }else if(i-j>1&&s.charAt(i)==s.charAt(j)&&dp[j+1][i-1]==1){
					 dp[j][i]=1;
				 }
				 //构建完成之后,查看是否更新最大值
				 if(dp[j][i]==1&&max<i-j+1) {
					 max=i-j+1;
					 start=j;
				 }
			 }
		 }		 
		 return s.substring(start, max+start);
	 }

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值