腾讯823校招笔试翻车经(请大家给点建议)

1. 删第k个链表节点。一开始傻乎乎的按照要求写,发现超时。
import java.util.Scanner;

public class Main {
    private static Node deleteNode(Node head, int k) {
        Node dum = new Node(0);
        dum.next = head;
        Node runner = dum;
        for (int i = 0; i < k-1; i++) {
        runner = runner.next;
        }
        Node nxt = runner.next.next; // runner.next should be deleted
        runner.next = nxt;
        return dum.next;
}

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int k = sc.nextInt();
        Node dum = new Node(0);
        Node tail = dum;
        System.out.println("before running");
        for(int i = 0; i < n; i++){
            Node cur = new Node(sc.nextInt());
            tail.next = cur;
            tail = cur;
        } 
        Node h = deleteNode(dum.next, k);
        Node runner = dum.next;
        while (runner != null) {
            System.out.print(runner.val + " ");
            runner = runner.next;
        }
    }
}

class Node {
int val;
Node next;

public Node (int v){
val = v;
}
}


优化成直接输出,还是超时,只能通过75%。浪费了30-40分钟(哭了)。请高人赐教,这题怎么写才能过?
```java
import java.util.Scanner;

public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int k = sc.nextInt();

for(int i = 0; i < k-1; i++){
int val = sc.nextInt();
System.out.print(val + " ");
}
sc.nextInt();
for(int i = k; i < n; i++){
int val = sc.nextInt();
System.out.print(val + " ");
}
}
}
```

2. 给定字符串str,找第k小distinct子串(排序为字典序升序)。
通过测试用例为0。不知道为啥,请高人赐教。
import java.util.*;

public class Main {
static HashSet<String> all = new HashSet();
    private static void construct(String str, int start, int len, StringBuilder sb) {
        if (sb.length() == len) {
            all.add(sb.toString());
            return;
        }
        int buf_len = sb.length();
        for (int i = start; i < str.length(); i++) {
            sb.append(str.charAt(i));
            construct(str, i+1, len, sb);
            sb.setLength(buf_len);
        }
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        String str = sc.nextLine();
        int k = sc.nextInt();
        int n = str.length();
        for (int len = 1; len <= n; len++)
            construct(str, 0, len, new StringBuilder());
        List<String> res = new ArrayList();
        for (String s: all)
            res.add(s);
        Collections.sort(res);
        System.out.println(res.get(k-1));
    }
}



3. 给定一个正数,拆成两个非负的数,位数和(每一个数字相加)最大。通过测试用例100%。
import java.util.*;
public class Main {
    static HashMap<Long, Long> mem = new HashMap();
    private static long getVal(long n){
        if (mem.containsKey(n))
            return mem.get(n);
        long res = 0;
        while (n > 0) {
            res += n % 10;
            n /= 10;
        }
        mem.put(n, res);
        return res;
    }

    private static long solve(long n) {
        if (n <= 18) return n;
        long num1 = 9;
        long best = 0;
        while (n - num1 > 0) {
            best = Math.max(best, getVal(num1) + getVal(n - num1));
            num1 = num1*10+9;
        }
        return best;
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int T = sc.nextInt();

        for (int t = 0; t < T; t++) {
            long n = sc.nextLong();
            System.out.println(solve(n));
        }
    }
}



4. 木板长度高度均为1,黑板可以横着擦,竖着擦。黑板高度由数组表示(输入第二行)。如果木板在擦黑板中间断了,需要重新开始擦。求最小的擦的次数。这题我不会做,当时放弃了。
样例如下
```
//5
//2 2 1 2 1
```
需要返回3。

经过参考@〢ヽ夜╰︶ ̄太美 的代码,考虑如下dp解法。并不保证正确。
public class Main {
    
    public static int paint(int[] arr) {
        int n = arr.length;
        int highest = 0;
        for (int h: arr)
            highest = Math.max(highest, h);
        // dp[i][j]: the min cost to paint first i blackboards already, height can achieve j
        int[][] dp = new int[n+1][highest+1];
        for (int j = 1; j <= highest; j++)
            dp[0][j] = j;
        for (int i = 1; i <= n; i++) 
            for (int j = 1; j <= highest; j++)
                dp[i][j] = n;
        
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= highest; j++) {
                // paint vertically 
                int h = Math.min(j, arr[i-1]);
                dp[i][h] = Math.min(dp[i][h], dp[i-1][j] + 1);
                // paint horizontally
                if (arr[i-1] < n) {
                    int cur = arr[i-1];
                    if (j >= arr[i-1]) 
                        dp[i][cur] = Math.min(dp[i][cur], dp[i-1][j]);
                    else
                        dp[i][cur] = Math.min(dp[i][cur], dp[i-1][j] + cur -j);
                }
            }
        }
        int res = n;
        
        for (int j = arr[n-1]; j <= highest; j++)
            res = Math.min(res, dp[n][j]);
        return res;
    }
    
    public static void main(String[] args) {
        int[] arr = new int[]{2,2,1,2,1};
        System.out.println(paint(arr));
    }
}
	




5. 给定字符串str,给定范围[l, r],求子串能拆成最少的回文串的个数。通过测试案例70-90%。不知道还可以怎么优化了,请高人赐教。
import java.util.*;

public class Main {

    static HashMap<String, Integer> mem = new HashMap();
    private static int splitPa(String key) {
        if (mem.containsKey(key))
            return mem.get(key);
        int n = key.length();
        int best = n;
        for (int i = 0; i < n; i++) {
            String right = key.substring(i);
            if (isPa(right)) {
                String left = key.substring(0, i);
                best = Math.min(best, 1 + splitPa(left));
            }
        }
        mem.put(key, best);
        return best;
    }

    private static boolean isPa(String str) {
        int l = 0;
        int r = str.length() - 1;
        while (l < r) {
            if (str.charAt(l) != str.charAt(r))
                return false;
            l++;
            r--;
        }
        return true;
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        String str = sc.nextLine();
        int Q = sc.nextInt();
        mem.put("", 0);
        for (int q = 0; q < Q; q++) {
            int l = sc.nextInt();
            int r = sc.nextInt();
            System.out.println(splitPa(str.substring(l-1, r)));
        }
    }
}


#笔试题目##腾讯#
全部评论
我觉得你第五题在求best上花了不少时间,如果best=1直接结束循环会不会更好一点
2 回复 分享
发布于 2020-08-23 23:10
哇,nowcoder不支持markdown,我人傻了。
1 回复 分享
发布于 2020-08-23 22:49
我也是哭了,第一题卡死75
点赞 回复 分享
发布于 2020-08-23 22:57

相关推荐

12-17 19:24
门头沟学院 Java
黑皮白袜臭脚体育生:看你后备隐藏能源多不多,最坏的情况就是每个星期的三天课程都不在周末,那么每个星期公司那边请一天半假,半天假请上午,上午正常上课,早点溜去请病假或者中午去请病假,然后坐高铁回公司,记得提前请学校那边实训课下午的病假,就说肚子痛,然后下午就公司上班,第二个实训周同样,但病假理由是牙齿痛,像肚子痛和牙齿痛这种校医院不方便查,会同意你出去检查的,很多时候都不需要你的检查报告,这里的问题就是最坏情况时距离过远的话可能要坐飞机才能赶上,然后请假的话不一定请了就有回应,可能要等老师,然后距离不远不近的情况到公司了也是迟到,得想个说辞掩盖一下,顺便晚上多加点班补下时间,特殊情况特殊处理,正常不建议加班常态化,这样每个星期可以多凑出来半天,老师面子也有了公司那边也不至于无法交差,就是有点费存粮,如果哪个星期的三天课有一天或两天在周末的话那就更好应对了。实习还是建议去,学校的课懂的都懂
点赞 评论 收藏
分享
12-07 21:21
东北大学 Java
点赞 评论 收藏
分享
评论
2
3
分享
牛客网
牛客企业服务