LeetCode 刷题--数组

面试题03 数组中重复的数字

找出数组中重复的数字。

在一个长度为 n 的数组 nums 里的所有数字都在 0~n-1 的范围内。数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。请找出数组中任意一个重复的数字。

示例 1:

输入:
[2, 3, 1, 0, 2, 5, 3]
输出:2 或 3

class Solution {
    public int findRepeatNumber(int[] nums) {

     int j = nums.length;
     Arrays.sort(nums);
     for(int i = 1 ; i< j ; i++){
         if(nums[i] == nums[i-1]) {
            return nums[i];

         }
     }
     return -1;
    }
}

287 寻找重复数

给定一个包含 n + 1 个整数的数组 nums,其数字都在 1 到 n 之间(包括 1 和 n),可知至少存在一个重复的整数。假设只有一个重复的整数,找出这个重复的数。

示例 1:

输入: [1,3,4,2,2]
输出: 2
示例 2:

输入: [3,1,3,4,2]
输出: 3

class Solution {
    public int findDuplicate(int[] nums) {
        //给定一个8个数字的数组,数组里数字范围应该是【1,7】
        //1,2,3,4,5,6,7
        //2,3,5,1,2,7,6,4
        //mid指向4,看小于等于4的个数,应该是4个
        //如果大于4个,说明【1,4】之间有重复
       int l =1;
       int r = nums.length -1;//[1,7]
       while(l < r){
           int mid = l+ (r-l)/2;
           int count=0;
           for(int i = 0; i<nums.length; i++){
               if(nums[i]<= mid)  count++;
           }
           //严格意义上讲,【1,4】区间内必需只出现4个数字
           if(count > mid ){
             r= mid;//在左边
           }else{
             l = mid+1;
           }   
       }
       return l;//注意返回下标的值
    }
}

class Solution {
    public int findDuplicate(int[] nums) {
        Arrays.sort(nums);
        for(int i = 1; i<nums.length; i++){
            if(nums[i] == nums[i-1])  return nums[i];
        }
        return -1;
    }
}

class Solution {
    public int findDuplicate(int[] nums) {
       Set<Integer> set = new HashSet<>();
       for(int num: nums){
           if(!set.add(num)) return num;
       }
       return -1;
    }
}

面试题 56-1 数组中数字出现的次数

一个整型数组 nums 里除两个数字之外,其他数字都出现了两次。请写程序找出这两个只出现一次的数字。要求时间复杂度是O(n),空间复杂度是O(1)。

示例 1:

输入:nums = [4,1,4,6]
输出:[1,6] 或 [6,1]
示例 2:

输入:nums = [1,2,10,4,1,4,3,3]
输出:[2,10] 或 [10,2]

class Solution {
    public int[] singleNumbers(int[] nums) {
     int arr[] = new int[10001];
     int i,j = 0;
     for(i = 0 ; i <nums.length; i++){
         arr[nums[i]]++;
     }
     for(i = 0 ; i <arr.length; i++){
         if(arr[i] == 1){
             nums[j] = i;
             j++;
         }
     }
     return new int[]{nums[0],nums[1]};
    }
}
class Solution {
    public int[] singleNumbers(int[] nums) {
     Set<Integer> set = new HashSet<>();
     for(int i = 0 ; i< nums.length; i++){
         if(set.contains(nums[i])) set.remove(nums[i]);
         else set.add(nums[i]);
     }

     return set.stream().mapToInt(Integer::intValue).toArray();
    }
//集合转为数组核心代码:
//list.stream().mapToInt(Integer::intValue).toArray();
}

class Solution {
    public int[] singleNumbers(int[] nums) {
     Arrays.sort(nums);
     Stack<Integer> stack  = new Stack<>();
     for(int num : nums){
         //挨个入栈,与栈顶相同就栈顶出栈,否则入栈
         
         if(stack.isEmpty())  stack.push(num);
         else{
             if(stack.peek() != num)  stack.push(num);
             else stack.pop();
         }
     }
     int[] res = new int[2];
     res[1] = stack.pop();
     res[0] = stack.pop();
     return res;
    }
}

class Solution {
    public int[] singleNumber(int[] nums) {
        int res[] = new int[2];
        int j = 0;
    HashMap<Integer, Integer> hashmap = new HashMap<>();
    for (int num : nums)
      hashmap.put(num, hashmap.getOrDefault(num, 0) + 1);
    for (int k : hashmap.keySet())
      if (hashmap.get(k) == 1) res[j++] = k;
   
   return res;
  }
}
class Solution {
    public int findDuplicate(int[] nums) {
       Map<Integer, Integer> map = new HashMap<>();
       for(int num: nums){
          map.put(num, map.getOrDefault(num, 0)+1);
       }
       for(int k: map.keySet()){
          if(map.get(k)>1) return k;
       }
       return -1;
        
    }
}

137. 只出现一次的数字

给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现了三次。找出那个只出现了一次的元素。

说明:

你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗?

示例 1:

输入: [2,2,3,2]
输出: 3
示例 2:

输入: [0,1,0,1,0,1,99]
输出: 99

class Solution {
    public int singleNumber(int[] nums) {
    HashMap<Integer, Integer> hashmap = new HashMap<>();
    for (int num : nums)
      hashmap.put(num, hashmap.getOrDefault(num, 0) + 1);
    for (int k : hashmap.keySet())
      if (hashmap.get(k) == 1) return k;
    return -1;
  }
}

面试题66. 构建乘积数组

给定一个数组 A[0,1,…,n-1],请构建一个数组 B[0,1,…,n-1],其中 B 中的元素 B[i]=A[0]×A[1]×…×A[i-1]×A[i+1]×…×A[n-1]。不能使用除法。

示例:

输入: [1,2,3,4,5]
输出: [120,60,40,30,24]

class Solution {
    public int[] constructArr(int[] a) {
   //除自身以外所有数组的乘积
   int[] left = new int[a.length];
   int[] right = new int[a.length];
   int[] ans = new int[a.length];
   int k = 1;
   for(int i = 0 ; i<a.length; i++){
       left[i] = k;//不乘自身
       k = k*a[i];
   }
   k=1;
   for(int i = a.length -1; i>=0 ;i--){
       right[i] = k;
       k= k*a[i];
   }
   for(int i = 0 ;i <a.length; i++){
       ans[i] = left[i]*right[i];
   }
    return ans;
    }
}

面试题04 二维数组的查找

在一个 n * m 的二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。

示例:

现有矩阵 matrix 如下:

[
  [1,   4,  7, 11, 15],
  [2,   5,  8, 12, 19],
  [3,   6,  9, 16, 22],
  [10, 13, 14, 17, 24],
  [18, 21, 23, 26, 30]
]
给定 target = 5,返回 true。

给定 target = 20,返回 false

此题中,需要根据矩阵的特殊性,
左下角数字:列中数字最大,行中数字最小
右上角数字:行中数字最大,列中数字最小

class Solution {
    public boolean findNumberIn2DArray(int[][] matrix, int target) {
    //二维数组查找,左下角标志数法
    //左下角数字是一列中最大的,一行中最小的
    int i = matrix.length-1;
    int j = 0;
    while(i>=0 && j <= matrix[0].length-1){
        if(matrix[i][j] == target) return true;
        else if(matrix[i][j] < target) j++;
        else i--;
    }
    return false;

    }
}

面试题 10.01 合并排序的数组

给定两个排序后的数组 A 和 B,其中 A 的末端有足够的缓冲空间容纳 B。 编写一个方法,将 B 合并入 A 并排序。

初始化 A 和 B 的元素数量分别为 m 和 n。

示例:

输入:
A = [1,2,3,0,0,0], m = 3
B = [2,5,6], n = 3

输出: [1,2,2,3,5,6]

class Solution {
    public void merge(int[] A, int m, int[] B, int n) {
//归并排序,从后往前
    int startA = m-1, startB = n-1, mergeAB = m+n-1;
    int  temp = 0;
    //如果AB都没有走完
    while(startA>=0 && startB >=0){
      if(A[startA] > B[startB]){
          A[mergeAB] = A[startA];
          mergeAB--;
          startA--;
      }else{
          A[mergeAB] = B[startB];
          mergeAB--;
          startB--;
      }
    }
    //B没有走完
    while(startB >=0){
          A[mergeAB] = B[startB];
          mergeAB--;
          startB--;
      }
      //A没有走完
     //不用管

    }
}

45. 把数组排成最小的数

输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。

示例 1:
输入: [10,2]
输出: “102”

示例 2:
输入: [3,30,34,5,9]
输出: “3033459”

Arrays 类中的 sort 方法承诺可以对对象数组进行排序,但要求满足下列条件:
对象所属的类必须实现 Comparable 接口,重写 compareTo 方法
String类型的数组可以直接调用sort函数
在Java中String和基本数据类型都默认已经实现了Comparable接口
->是lambda表达式,就是匿名函数。
最简单的例子是 Collections.sort(list, (x, y) -> y - x); 其中
(x, y) -> y - x是一个lambda表达式,输入两个参数x, y,返回值 y-x。“->”起分隔作用,Java会自动翻译。
左侧:Lambda 表达式的参数列表
右侧:Lambda 表达式中所需执行的功能, 即 Lambda 体

class Solution {
    public String minNumber(int[] nums) {
    //新建一个字符串数组
    String[] strNumbers  = new String[nums.length];
    
    for(int i = 0; i<nums.length; i++){
        strNumbers[i] = String.valueOf(nums[i]);
    }
    //排序
    //sort函数参数可以为类
    Arrays.sort(strNumbers, new Comparator<String>() {
        @Override
        public int compare(String o1, String o2){
            return (o1 + o2).compareTo(o2 + o1);
            
        }
    });
    //将该字符串元素拼接起来
    StringBuilder builder = new StringBuilder();
    for(int i= 0; i<strNumbers.length; i++){
        builder.append(strNumbers[i]);
    }
    return builder.toString();

    }
    /*升序排的话就是第一个参数.compareTo(第二个参数)
   降序排的话就是第二个参数.compareTo(第一个参数)
*/
}

class Solution {
    public String minNumber(int[] nums) {
    List<String> list = new ArrayList<>();
    for(int num: nums){
        list.add(String.valueOf(num));
    }
    list.sort((o1,o2) -> (o1+o2).compareTo(o2+o1));
    //把sort函数里面的o1,o2参数改为o1+o2
    return String.join("",list);
    //join用于字符串拼接
    //String[] arrStr=new String[]{"a","b","c"};a-b-c
     //System.out.println(String.join("-", arrStr));
     //输出结果是 a-b-c
    }
}

《compare(T o1, T o2)是中的o1,o2代表什么,是怎么实现排序的?怎么和compareTo()配合使用?

答:o1和o2每次只取一个数据,就一次只比较两个数据,假如比较7,8,9,5,6,那么第一次比较o1先取8,o2取7(很奇怪,我当时以为是顺着取值,但是很奇怪,他是相邻两个值逆着取值,但不管他,开心就好),接下来配合compareTo()实现这两个数的排序,o1.compareTo(o2)会返回一个int值,如果0说明o1和o2相等,如果返回负值,那么o1和o2会倒序排序,返回正值,那么o1和o2会正序排序。返回值之后这两个值就进行了排序,至此,这两个值已经排序好了,接下来第二次排序,o1取9,o2取8,第三次o1取5,o2取9…

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章