字节笔试

public class 循环依赖 {

    /**  本质上就是拓扑排序问题
     * 在完成A之前需要先完成B,B之前需要C以此类推
     * 点的范围[1,9]
     * 此题不难拓扑排序的板板,搞懂输入就行
     * 输入
     * 第一行 t 表示一共有t行数据
     * 第二行 一列数[1,9] 表示 询问他们能否完成
     * 接下来每行代表依赖关系
     * 每一行 第一个数x 后面的数都是x的依赖 a b c.... (在完成x之前必须完成它所依赖的那些)
     */
    public static void main(String[] args) {
        ArrayList<Integer> query = new ArrayList<>();
        Scanner sc = new Scanner(System.in);
        int t = sc.nextInt() - 1;
        sc.nextLine();
        String[] s = sc.nextLine().split(" ");
        for (String x : s) {
            query.add(Integer.parseInt(x));
        }

        List<Integer>[] g = new ArrayList[10];
        Arrays.setAll(g, k -> new ArrayList<>(10));
        int[] degree = new int[10];
        Arrays.fill(degree, -1);
        for (int k = 0; k < t; k++) {
            String[] nums = sc.nextLine().split(" ");
            int x = 0, y;
            for (int i = 0; i < nums.length; i++) {
                if (i == 0) {
                    x = Integer.parseInt(nums[i]);
                } else {
                    y = Integer.parseInt(nums[i]);
                    g[y].add(x);
                    if (degree[y] == -1) {
                        degree[y] = 0;
                    }
                    if (degree[x] == -1) {
                        degree[x] = 1;
                    } else {
                        degree[x]++;
                    }
                }
            }
        }

        ArrayDeque<Integer> q = new ArrayDeque<>();
        for (int i = 1; i < degree.length; i++) {
            if (degree[i] == 0)
                q.offer(i);
        }

        while (!q.isEmpty()) {
            int y = q.poll();
            for (int x : g[y]) {
                degree[x]--;
                if (degree[x] == 0)
                    q.offer(x);
            }
        }
        for (int u : query) {
            // 可以完成入度为0 输出1,完不成就输出0
            int res = degree[u] == 0 ? 1 : 0;
            System.out.print(res + " ");
        }
    }
}

public class 最大乘积子数组 {

    /**  值得注意的点:直接保存乘积会爆long,可以把2^10以内的预存这样就可以O(1)得到一个数是2的多少次幂
                
     * 数组nums 索引从1开始
     * nums[i] 属于 {0,1,2,4,8,16,32,64,....,1024}
     * 求乘积最大的子数组的区间
     * 有多行测试集
     * 输入描述
     * 第一行输入t表示有t个测试用例
     * 每个测试用例由2行组成
     *
     * 第1个用例:
     * 第一行  数组长度n
     * 第二行 数组
     * 第2个用例:
     * 第一行 n
     * 第二行 数组
     */
    static int[] map = new int[1025];

    static {
        for (int i = 0; i <= 10; i++) {
            map[1 << i] = i;
        }
    }

    static int N = (int) 1e4;
    static int[] nums = new int[N + 1];

    public static void main(String[] args) {
        // write your code here
        Scanner sc = new Scanner(System.in);
        int t = sc.nextInt();
        for (int k = 0; k < t; k++) {
            int n = sc.nextInt();
            int cru = 0;
            int max = 0;

            int x = 1, y = 1;
            for (int i = 1, j = 1; i <= n; i++) {
                nums[i] = sc.nextInt();
                if (nums[i] != 0) {
                    cru += map[nums[i]];
                } else {
                    j = i + 1;
                    cru = 0;
                }
                if (cru > max) {
                    x = j;
                    y = i;
                    max = cru;
                }
            }

            System.out.printf("%d %d", x, y);
            System.out.println();

        }
    }
}

这题当时没想出来考完补的
public class 翻转子数组后的最大子段和 {
    static long MIN = -(Long.MAX_VALUE >> 20);

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int[] nums = new int[n];
        for (int i = 0; i < nums.length; i++) {
            nums[i] = sc.nextInt();
        }

        // 以k结尾的最大字段和 + 后半段的最大后缀和
        // 多余的部分可以认为通过翻转被删掉
        //  nums[0~k~n-1]
        //  0 1 2 ... l...k....r r+1 ..... n-1
        //   k+1~r可以认为被删除了 r+1~n-1重新续上sum[k]
        // dp[j]表示从右开始的最大后缀和

        // 复杂度分析
        // 找前半段是的字段和 O(N) + 后半段以O(1)找到最大后缀
        // 总复杂度O(N)
        long[] dp = new long[n + 1];
        long sum = 0, max = MIN;
        dp[n] = MIN;
        for (int j = n - 1; j >= 0; j--) {
            sum += nums[j];
            dp[j] = Math.max(sum, dp[j + 1]);
        }
        sum = 0;
        long res = MIN;
        dp[n] = 0;
        for (int i = 0; i < n; i++) {
                 // fixed 修复最大子段和
            sum =  Math.max(sum + nums[i], nums[i]);
            max = Math.max(max, sum);
            res = Math.max(res, max + dp[i + 1]);
        }
        System.out.println(res);

    }
}


public class 长为k的子数组最大和 {
    /**
     *  可以在n个元素的数组中去掉一个元素
     *  求长为k的子数组的最大和
     *  输入:
     *  5 3
     *  2 1 3 -1 4
     *  输出:
     *  8
     *  解释:去掉-1后  {1, 3, 4}组成k=3的子数组和最大 8
     */
    public static void main(String[] args) {
        // 基本思路就是滑动窗口+单调队列
        // 单调队列维护窗口 最小值的索引
        // 淘汰最小值之后 找到窗口两端相邻的元素补进来
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int k = sc.nextInt();
        int[] nums = new int[n];
        for (int i = 0; i < nums.length; i++) {
            nums[i] = sc.nextInt();
        }
        ArrayDeque<Integer> q = new ArrayDeque<>(k + 1);
        int sum = 0;
        int res = 0;
        for (int i = 0; i < nums.length; i++) {
            // 窗口现成 左端滑出 sum减掉
            if (i >= k) {
                sum -= nums[i - k];
            }
            sum += nums[i];
            while (!q.isEmpty() && nums[i] <= nums[q.peekLast()])
                q.removeLast();
            q.offer(i);

            // 如果对头已经滑出窗口 淘汰
            if (!q.isEmpty() && i - q.peekFirst() + 1 > k) {
                q.removeFirst();
            }
            // 形成了k大小的窗口
            if (i >= k - 1) {
                int x, y = 0, z = 0;
                assert !q.isEmpty();
                x = nums[q.peekFirst()];
                if (i + 1 < nums.length) {
                    y = nums[i + 1];
                }
                if (i >= k)
                    z = nums[i - k];
                // 把窗口内最小元素淘汰 用相邻更大价值的补回来 不然相当于当前窗口不删除元素就已经最大
                res = sum - x + Math.max(Math.max(x, y), z);
            }
        }
        System.out.println(res);

    }
}








#字节笔试#
全部评论
感谢分享,学习一下,希望有机会面试字节
点赞
送花
回复
分享
发布于 2022-09-28 09:29 江苏

相关推荐

2 6 评论
分享
牛客网
牛客企业服务