字节刷题记录

字节刷题记录

一、字节跳动2019春招研发部分编程题

1、(字符串)万万没想到之聪明的编辑

我叫王大锤,是一家出版社的编辑。我负责校对投稿来的英文稿件,这份工作非常烦人,因为每天都要去修正无数的拼写错误。但是,优秀的人总能在平凡的工作中发现真理。我发现一个发现拼写错误的捷径:

  1. 三个同样的字母连在一起,一定是拼写错误,去掉一个的就好啦:比如 helllo -> hello
  2. 两对一样的字母(AABB型)连在一起,一定是拼写错误,去掉第二对的一个字母就好啦:比如 helloo -> hello
  3. 上面的规则优先“从左到右”匹配,即如果是AABBCC,虽然AABB和BBCC都是错误拼写,应该优先考虑修复AABB,结果为AABCC

我特喵是个天才!我在蓝翔学过挖掘机和程序设计,按照这个原理写了一个自动校对器,工作效率从此起飞。用不了多久,我就会出任CEO,当上董事长,迎娶白富美,走上人生巅峰,想想都有点小激动呢!

……

万万没想到,我被开除了,临走时老板对我说: “做人做事要兢兢业业、勤勤恳恳、本本分分,人要是行,干一行行一行。一行行行行行;要是不行,干一行不行一行,一行不行行行不行。” 我现在整个人红红火火恍恍惚惚的……

请听题:请实现大锤的自动校对程序

数据范围: 1<=n<=50 ,每个用例的字符串长度满足1<=l<=1000

  • 思路1:利用 StringBuild 判断/双指针法

    • public static void main(String[] args) {
              Scanner scanner = new Scanner(System.in);
              int count = Integer.parseInt(scanner.nextLine());
              List<String> result = new ArrayList<>();
              for (int i = 0; i < count; i++) {
                  StringBuilder des = new StringBuilder();
                  String src = scanner.nextLine();
                  for (int j = 0; j < src.length(); j++) {
                      int len = des.length();
                      // 如果目标字符串长度大于1,并且最后一个字符和当前字符相同时进行比较
                      if (len > 1 && src.charAt(j) == des.charAt(len - 1)) {
                          // 1.倒数第一个和倒数第二个相同(符合AAA)
                          // 2.倒数第二个和倒数第三个相同(符合AABB)
                          if ((des.charAt(len - 1) == des.charAt(len - 2))
                                  || (len > 2 && des.charAt(len - 2) == des.charAt(len - 3))) {
                              continue;
                          }
                      }
                      des.append(src.charAt(j));
                  }
                  result.add(des.toString());
              }
              result.forEach(System.out::println);
              scanner.close();
          }
      
      
  • 思路2:自动机

  • 思路3:正则表达式

    • public class Main {
          public static void main(String[] args) {
              Scanner scanner = new Scanner(System.in);
              int line = scanner.nextInt();
              scanner.nextLine();
              for (int i = 0; i < line; i++) {
                  System.out.println(
                      scanner.nextLine()
                      .replaceAll("(.)\\1+","$1$1")
                      .replaceAll("(.)\\1(.)\\2","$1$1$2")
                  );
              }
          }
      }
      
    • 正则含义

      • (.)\\1+ 表示 表示任意一个字符重复两次或两次以上
      • .表示任意字符,后面的\1表示取第一个括号匹配的内容,后面的加号表示匹配1次或1次以上。二者加在一起就是某个字符重复两次或两次以上
      • (.)\\2表示取第二个括号中匹配的字符,(.)\\1(.)\\2即表示形如AABB
      • $1是第一个小括号里的内容,$2是第二个小括号里面的内容

2、(数组、组合)万万没想到之抓捕孔连顺

我叫王大锤,是一名特工。我刚刚接到任务:在字节跳动大街进行埋伏,抓捕恐怖分子孔连顺。和我一起行动的还有另外两名特工,我提议

  1. 我们在字节跳动大街的 N 个建筑中选定 3 个埋伏地点。
  2. 为了相互照应,我们决定相距最远的两名特工间的距离不超过 D 。

我特喵是个天才! 经过精密的计算,我们从X种可行的埋伏方案中选择了一种。这个方案万无一失,颤抖吧,孔连顺!

……

万万没想到,计划还是失败了,孔连顺化妆成小龙女,混在cosplay的队伍中逃出了字节跳动大街。只怪他的伪装太成功了,就是杨过本人来了也发现不了的!

请听题:给定 N(可选作为埋伏点的建筑物数)、 D(相距最远的两名特工间的距离的最大值)以及可选建筑的坐标,计算在这次行动中,大锤的小队有多少种埋伏选择。

注意:

  1. 两个特工不能埋伏在同一地点
  2. 三个特工是等价的:即同样的位置组合( A , B , C ) 只算一种埋伏方法,不能因“特工之间互换位置”而重复使用

输入要求:

第一行包含空格分隔的两个数字 N和D(1 ≤ N ≤ 1000000; 1 ≤ D ≤ 1000000)第二行包含N个建筑物的的位置,每个位置用一个整数(取值区间为[0, 1000000])表示,从小到大排列(将字节跳动大街看做一条数轴)

输出要求:

一个数字,表示不同埋伏方案的数量。结果可能溢出,请对 99997867 取模
  • 双指针法 组合

    • 快指针先找到第一个大于D的位置 j ,然后从慢指针 i 到快指针前一个位置进行选择(组合问题)

    • 由于从 i 到 j - 1中选3个,到下一次再选会出现重复,所以固定第一个值,从后面选两个

      • 例,1 2 3 4,i = 0, j = 3,从1 - 4中选3个会有4种情况,再i = 1, j = 3时从 2 - 4中选3中也会有1种情况,但这种情况再 1 - 4中选过了(2 3 4)
      • 组合公式: C r n = n ! r ! ( n − r ) ! C_{r}^{n}= \frac{n!}{r!\left (n - r \right )!} Crn=r!(nr)!n!,组合是没有顺序的,有顺序的是排列
    • 代码(ps. 这么简单的代码为啥我就写不出来呢)

      public static void main (String[] args){
              Scanner sc=new Scanner(System.in);
              int N=sc.nextInt();
              int D=sc.nextInt();
              int []s=new int[N];
              long num=0;
              for(int i=0;i<N;i++){
                  s[i]=sc.nextInt();
              }
              for(int i=0,j=i+2;i<N-2;i++){
                  long p;
                  while(j<N&&(s[j]-s[i]<=D))
                      j++;
                  p=j-i-1;
                  num=num+(p*(p-1)/2);
              }
              System.out.println(num%99997867);
          }
      

3、(模拟、回溯)雀魂启动!

小包最近迷上了一款叫做雀魂的麻将游戏,但是这个游戏规则太复杂,小包玩了几个月了还是输多赢少。

于是生气的小包根据游戏简化了一下规则发明了一种新的麻将,只留下一种花色,并且去除了一些特殊和牌方式(例如七对子等),具体的规则如下:

  1. 总共有36张牌,每张牌是1~9。每个数字4张牌。
  2. 你手里有其中的14张牌,如果这14张牌满足如下条件,即算作和牌
  • 14张牌中有2张相同数字的牌,称为雀头。
  • 除去上述2张牌,剩下12张牌可以组成4个顺子或刻子。顺子的意思是递增的连续3个数字牌(例如234,567等),刻子的意思是相同数字的3个数字牌(例如111,777)

例如:

1 1 1 2 2 2 6 6 6 7 7 7 9 9 可以组成1,2,6,7的4个刻子和9的雀头,可以和牌

1 1 1 1 2 2 3 3 5 6 7 7 8 9 用1做雀头,组123,123,567,789的四个顺子,可以和牌

1 1 1 2 2 2 3 3 3 5 6 7 7 9 无论用1 2 3 7哪个做雀头,都无法组成和牌的条件。

现在,小包从36张牌中抽取了13张牌,他想知道在剩下的23张牌中,再取一张牌,取到哪几种数字牌可以和牌。

输入只有一行,包含13个数字,用空格分隔,每个数字在1~9之间,数据保证同种数字最多出现4次。
输出同样是一行,包含1个或以上的数字。代表他再取到哪些牌可以和牌。若满足条件的有多种牌,请按从小到大的顺序输出。若没有满足条件的牌,请输出一个数字0
  • 回溯

    • 只有9张牌,挨个放进去

    • 回溯:雀头挨个检查,不行就回溯

    • 如果不是刻子就一定是顺子,不是就回溯

    • Map不能直接作为形参传递,会改变;Java中只有值传递,对象传递的是引用

    • public static boolean judge(TreeMap<Integer, Integer> map,int count) {
              boolean flag = false;
              if (count == 0) return true;
              for (Integer i : map.keySet()) {
                  if(map.get(i) >= 3){
                      map.put(i,map.get(i)-3);
                      flag = judge(map,count-3);
                      if(flag) return true;
                      map.put(i,map.get(i)+3);
                  }
                  if(map.get(i) > 0){
                      if(map.containsKey(i+1) && map.containsKey(i+2) && map.get(i+1)>0 && map.get(i+2)>0){
                          map.put(i,map.get(i)-1);
                          map.put(i+1,map.get(i+1)-1);
                          map.put(i+2,map.get(i+2)-1);
                          flag =  judge(map,count-3);
                          if(flag) return true;
                          map.put(i,map.get(i)+1);
                          map.put(i+1,map.get(i+1)+1);
                          map.put(i+2,map.get(i+2)+1);
                      }else return false;
                  }
              }
      
              return false;
          }
      
          public static void main(String[] args) {
              Scanner sc = new Scanner(System.in);
              int[] arr = new int[13];
              TreeMap<Integer, Integer> map = new TreeMap<>();
              ArrayList<Integer> ans = new ArrayList<>();
              for (int i = 0; i < 13; i++) {
                  arr[i] = sc.nextInt();
                  if (map.containsKey(arr[i])) {
                      map.put(arr[i], map.get(arr[i]) + 1);
                  } else {
                      map.put(arr[i], 1);
                  }
              }
              sc.close();
              for(int i = 1;i<= 9;i++){
                  if(map.containsKey(i)){
                      if(map.get(i)<4){
                          map.put(i,map.get(i)+1); // 挨个放牌
                          boolean flag = false;
                          for(int j : map.keySet()){ // 挨个取雀头
                              if(map.get(j)>=2){
                                  map.put(j,map.get(j)-2); // 去掉雀头
                                  TreeMap<Integer, Integer> map_ = new TreeMap<>();
                                  map_.putAll(map);
                                  flag = judge(map_, 12);
                                  if(flag) {
                                      ans.add(i); // 加对的牌
                                      map.put(j,map.get(j)+2); // 把雀头放回去
                                      break; // 结束这次雀头
                                  }
                                  map.put(j,map.get(j)+2);
                              }
                          }
                          map.put(i,map.get(i)-1);
                      }
                  }else {
                      map.put(i,1); // 挨个放牌
                      boolean flag = false;
                      for(int j : map.keySet()){
                          if(map.get(j)>=2){
                              map.put(j,map.get(j)-2);
                              TreeMap<Integer, Integer> map_ = new TreeMap<>();
                              map_.putAll(map);
                              flag = judge(map_, 12);
                              if(flag) {
                                  ans.add(i);
                                  map.put(j,map.get(j)+2);
                                  break;
                              }
                           map.put(j,map.get(j)+2);
                          }
                      }
      //                map.put(i,0);
                      map.remove(i);
                  }
              }
              for(int i : ans) System.out.println(i);
          }
      

4、(模拟)特征提取

​ 小明是一名算法工程师,同时也是一名铲屎官。某天,他突发奇想,想从猫咪的视频里挖掘一些猫咪的运动信息。为了提取运动信息,他需要从视频的每一帧提取“猫咪特征”。一个猫咪特征是一个两维的vector。如果x_1=x_2 and y_1=y_2,那么这俩是同一个特征。

​ 因此,如果喵咪特征连续一致,可以认为喵咪在运动。也就是说,如果特征在持续帧里出现,那么它将构成特征运动。比如,特征在第2/3/4/7/8帧出现,那么该特征将形成两个特征运动2-3-4 和7-8。

现在,给定每一帧的特征,特征的数量可能不一样。小明期望能找到最长的特征运动。

输入描述:
第一行包含一个正整数N,代表测试用例的个数。每个测试用例的第一行包含一个正整数M,代表视频的帧数。接下来的M行,每行代表一帧。其中,第一个数字是该帧的特征个数,接下来的数字是在特征的取值;比如样例输入第三行里,2代表该帧有两个猫咪特征,<1,1>和<2,2>所有用例的输入特征总数和<100000N满足1≤N≤100000,M满足1≤M≤10000,一帧的特征个数满足 ≤ 10000。特征取值均为非负整数。
输出描述:
对每一个测试用例,输出特征运动的长度作为一行
输入例子1:
1
8
2 1 1 2 2
2 1 1 1 4
2 1 1 2 2
2 2 2 1 4
0
0
1 1 1
1 1 1
输出例子1:
3
例子说明1:
特征<1,1>在连续的帧中连续出现3次,相比其他特征连续出现的次数大,所以输出3
  • 如何存储数组,如何保存连续值,如何判断最大值

    • public static void main(String[] args) {
              Scanner sc = new Scanner(System.in);
              int n = sc.nextInt();
              HashMap<String,Integer> map = new HashMap<>();
              for(int t = 0;t<n;t++){
                  int m = sc.nextInt();
                  HashMap<String,ArrayList<Integer>> list = null;
                  int max = 1;
                  for(int i = 0;i<m;i++){
                      HashMap<String,ArrayList<Integer>> list_0 = new HashMap<>();
                      HashMap<String,Integer> map_ = new HashMap<>();
                      int s = sc.nextInt();
                      for(int ss = 0;ss<s;ss++){
                          int p = sc.nextInt();
                          int q = sc.nextInt();
                          if(!list_0.containsKey(p+"")){
                              list_0.put(p+"",new ArrayList<>());
                          }
                          list_0.get(p+"").add(q);
                          if(list!=null){
                              if(list.containsKey(p+"") && list.get(p+"").contains(q)){
                                  if(map.containsKey(p+" "+q)){
                                      int tmp = map.get(p+" "+q);
                                      map_.put(p+" "+q,tmp+1);
                                      max = max >= tmp+1 ? max:tmp+1;
                                  }else {
                                      map_.put(p+" "+q,2);
                                      max = max >= 2 ? max:2;
                                  }
                              }
                          }
                      }
                      map = map_;
                      list = list_0;
                  }
                  System.out.println(max);
              }
          }
      

二、字节面试题猜测

1、(动态规划)接雨水

字节刷题记录_第1张图片

给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水

输入:height = [0,1,0,2,1,0,1,3,2,1,2,1]
输出:6
解释:上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度图,在这种情况下,可以接 6 个单位的雨水(蓝色部分表示雨水)。

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/trapping-rain-water

  • 遍历两边,从左往右找左边最大边 d p [ i ] = m a x ( h e i g h t [ i ] , d p [ i − 1 ] ) dp[i]=max(height [i],dp[i-1]) dp[i]=max(height[i],dp[i1]);从右往左找右边最大的边 d p 2 [ i ] = m a x ( h e i g h t [ i ] , d p 2 [ i + 1 ] ) dp2[i]=max(height [i],dp2[i+1]) dp2[i]=max(height[i],dp2[i+1])

  • class Solution {
        public int trap(int[] height) {
            int n = height.length;
            if (n == 0) {
                return 0;
            }
    
            int[] leftMax = new int[n];
            leftMax[0] = height[0];
            for (int i = 1; i < n; ++i) {
                leftMax[i] = Math.max(leftMax[i - 1], height[i]);
            }
    
            int[] rightMax = new int[n];
            rightMax[n - 1] = height[n - 1];
            for (int i = n - 2; i >= 0; --i) {
                rightMax[i] = Math.max(rightMax[i + 1], height[i]);
            }
    
            int ans = 0;
            for (int i = 0; i < n; ++i) {
                ans += Math.min(leftMax[i], rightMax[i]) - height[i];
            }
            return ans;
        }
    }
    

2、(动态规划、bfs)接雨水Ⅱ

字节刷题记录_第2张图片

给你一个 m x n 的矩阵,其中的值均为非负整数,代表二维高度图每个单元的高度,请计算图中形状最多能接多少体积的雨水。

输入: heightMap = [[1,4,3,1,3,2],[3,2,1,3,2,4],[2,3,3,2,3,1]]
输出: 4
解释: 下雨后,雨水将会被上图蓝色的方块中。总的接雨水量为1+2+1=4。

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/trapping-rain-water-ii

  • 一开始尝试使用每一层进行bfs判断,想法应该也没错,但是不知道那里写错了过了一半
  • 假设方块的索引为 ( i , j ) (i,j) (i,j),方块的高度为 heightMap [ i ] [ j ] h e i g h t M a p [ i ] [ j ] \textit{heightMap}[i][j]heightMap[i][j] heightMap[i][j]heightMap[i][j],方块接水后的高度为 water [ i ] [ j ] w a t e r [ i ] [ j ] \textit{water}[i][j]water[i][j] water[i][j]water[i][j]。则我们知道方块 (i,j) 的接水后的高度为:

w a t e r [ i ] [ j ] = m a x ( h e i g h t M a p [ i ] [ j ] , m i n ( w a t e r [ i − 1 ] [ j ] , w a t e r [ i + 1 ] [ j ] , w a t e r [ i ] [ j − 1 ] , w a t e r [ i ] [ j + 1 ] ) ) water[i][j]=max(heightMap[i][j],min(water[i−1][j],water[i+1][j],water[i][j−1],water[i][j+1])) water[i][j]=max(heightMap[i][j],min(water[i1][j],water[i+1][j],water[i][j1],water[i][j+1]))

  • 思想:先把水接满,然后判断边界应该是多高,然后bfs旁边的除了实际高度,不能比我高

  • 方案:bfs(最小堆看着有点麻烦就用能理解了的吧),时间复杂度: O ( M 2 N 2 ) O(M^2N^2) O(M2N2)

  • class Solution {
        public int trapRainWater(int[][] heightMap) {
            int m = heightMap.length;
            int n = heightMap[0].length;
            int[] dirs = {-1, 0, 1, 0, -1};
            int maxHeight = 0;
            
            for (int i = 0; i < m; ++i) {
                for (int j = 0; j < n; ++j) {
                    // 找到最大的点
                    maxHeight = Math.max(maxHeight, heightMap[i][j]);
                }
            }
            int[][] water = new int[m][n];
            for (int i = 0; i < m; ++i) {
                for (int j = 0; j < n; ++j){
                    water[i][j] = maxHeight; // 全部初始化为最大      
                }
            }  
            Queue<int[]> qu = new LinkedList<>();
            for (int i = 0; i < m; ++i) {
                for (int j = 0; j < n; ++j) {
                    if (i == 0 || i == m - 1 || j == 0 || j == n - 1) {
                        // 将边界并且不是最大的点加入队列,设置他们接水后的高为自己
                        if (water[i][j] > heightMap[i][j]) {
                            water[i][j] = heightMap[i][j];
                            qu.offer(new int[]{i, j});
                        }
                    }
                }
            } 
            while (!qu.isEmpty()) {
                int[] curr = qu.poll();
                int x = curr[0];
                int y = curr[1];
                for (int i = 0; i < 4; ++i) {
                    int nx = x + dirs[i], ny = y + dirs[i + 1];
                    if (nx < 0 || nx >= m || ny < 0 || ny >= n) {
                        // 判断是否越界
                        continue;
                    }
                    if (water[x][y] < water[nx][ny] && water[nx][ny] > heightMap[nx][ny]) {
                        // 判断1:当旁边的比我高时
                        // 判断2:当旁边的接满水还比他本身高时
    
                        // 旁边的等于自己的高或者我的水平面
                        water[nx][ny] = Math.max(water[x][y], heightMap[nx][ny]);
                        qu.offer(new int[]{nx, ny});
                    }
                }
            }
    
            // 最后记录一共接了多少水
            int res = 0;
            for (int i = 0; i < m; ++i) {
                for (int j = 0; j < n; ++j) {
                    res += water[i][j] - heightMap[i][j];
                }
            }
            return res;
        }
    }
    

3、(树、dfs、bfs) 二叉树中所有距离为 K 的结点

字节刷题记录_第3张图片

给定一个二叉树(具有根结点 root), 一个目标结点 target ,和一个整数值 k 。

返回到目标结点 target 距离为 k 的所有结点的值的列表。 答案可以以 任何顺序 返回。

节点数在 [1, 500] 范围内
0 <= Node.val <= 500
Node.val 中所有值 不同
目标结点 target 是树上的结点。
0 <= k <= 1000

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/all-nodes-distance-k-in-binary-tree

  • 思路1:DFS,记录所有节点的父节点(用hashmap),然后从target开始dfs(注意不能搜索过去又回来)

  • 思路2:树转图+BFS,一共就501个值,转成一张501*501的图,权重是1,bfs

  • class Solution {
        ArrayList<Integer> list = new ArrayList<>();
        HashMap<TreeNode,TreeNode> map = new HashMap<>();
        // 记录父节点
        public void dfs(TreeNode root){
            if(root == null) return;
            if(root.left!=null){
                map.put(root.left,root);
                dfs(root.left);
            }
            if(root.right!=null){
                map.put(root.right,root);
                dfs(root.right);
            }
        }
        // dfs找距离为k的节点
        public void dfs2(TreeNode target, TreeNode from, int n, int k){
            if(target==null) return;
            if(n==k) list.add(target.val);
            if(target.left!=null && target.left != from) dfs2(target.left,target,n+1,k);
            if(target.right!=null && target.right != from) dfs2(target.right,target,n+1,k);
            if(map.get(target) != from) dfs2(map.get(target),target,n+1,k);
        }
        public List<Integer> distanceK(TreeNode root, TreeNode target, int k) {
            map.put(root,null);
            dfs(root);
            dfs2(target,null,0,k);
            return list;
        }
    }
    

4、树的操作集合

  • 二叉树的层序遍历
    • bfs,记录队列的大小然后遍历整个队列
  • 【剑指offer】重建二叉树

    • 给定节点数为 n 的二叉树的前序遍历和中序遍历结果,请重建出该二叉树并返回它的头结点。

    • 递归法建树,前序的找根,然后中序根左为左子树,中序根右为右子树

  • 【剑指offer】二叉树中两个节点的最近公共祖先

    • 前序遍历,然后存入栈中(用arraylist模拟),两个栈分别对应两个节点路径,最后一个相同的就是

5、链表

  • 两个链表的第一个公共节点
    • 各设一个指针,然后相同速度,第二次相遇那个值
  • 判断是不是有环
    • 快慢指针,一个每次走俩,一个每次走一个

6、其他

  • 数值的整数次方
    • 实现 pow(x, n) ,即计算 x 的 n 次幂函数(即,xn)。不得使用库函数,同时不需要考虑大数问题

    • 快速幂, x n x^n xn,当n是偶数时 y = x n / 2 , x n = y ∗ y y=x^{n/2},x^n=y*y y=xn/2,xn=yy,奇数是就是 y ∗ y ∗ x y*y*x yyx

  • 快排

三、实际题目

  • (曼哈顿距离)给你一堆坐标,求这一堆数据中所有两两之间的曼哈顿距离之和,曼哈顿距离定义为 ∣ x i − x j ∣ + ∣ y i − y j ∣ |x_i - x_j| + |y_i - y_j| xixj+yiyj, 要求时间复杂度小于 n 2 n^2 n2
    • x和y相对独立所以分开算一个就行了
    • 去掉绝对值就相当于大的减小的,排序之后发现规律,例如 ( 1 , 1 ) ( 2 , 2 ) ( 3 , 3 ) (1,1) (2,2) (3,3) (1,1)(2,2)(3,3)三个点,光看x的话去掉绝对值 3 − 2 , 3 − 1 , 2 − 1 3-2,3-1,2-1 32,31,21,其中 + 3 +3 +3出现了 n − 1 n-1 n1次, − 3 -3 3出现了 0 0 0次,同理 + 2 +2 +2出现了 n − 2 n-2 n2次, − 2 -2 2出现了 1 1 1次。出现规律,从后往前加了第 i i i个数 i i i次,减了第 i i i个数 n − 1 − i n-1-i n1i
import java.util.*;
public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int []x = new int [n];
        int []y = new int [n];
        for(int i = 0;i<n;i++){
            x[i] = sc.nextInt();
            y[i] = sc.nextInt();
        }
        sc.close();
        Arrays.sort(x);
        Arrays.sort(y);
        int ans = 0;
        for(int i = n-1;i>=0;i--){
            ans += x[i] * i - x[i] * (n - 1 - i);
            ans += y[i] * i - y[i] * (n - 1 - i);
        }
        System.out.println(ans);
    }
}

你可能感兴趣的:(笔试复习,java,开发语言)