美文网首页Android进阶之路
每日一刷“面试题”,面试必过!之数据结构:数组(3)

每日一刷“面试题”,面试必过!之数据结构:数组(3)

作者: 码农的地中海 | 来源:发表于2022-05-11 19:29 被阅读0次

想要面试过的去,必须每日一刷题!

关于Android面试这里我就不多讲了,直接上题。

面试题:

1.寻找数组中第二小的元素

  1. 直接排序(冒泡n^2、快排nlgn)根据索引找到对应值
  2. 遍历一次,定义两个变量:一个变量用来存储数组的最大数,初始值为数组首元素,另一个变量用来存储第二大的数。

编码:

1. public static void findSecond(int a[]){
2.         if(a.length<3){
3.             System.out.println("数组太小");
4.         }
5.         int max=0,min=0;
6.         for (int i=1;i<a.length;i++){
7.             if(a[i]>=a[i-1]&&i<2){//确定两个最大初始值
8.                 max=a[i];
9.                 min=a[i-1];
10.                 continue;
11.             }
12.             if(a[i]>max&&i>1){//大于最大值
13.                 min=max;
14.                 max=a[i];
15.             }
16.             if(a[i]<max&&a[i]>min&&i>1){//介于两者之间
17.                 min=a[i];
18.             }
19.         }
20.         System.out.println("max:"+max);
21.         System.out.println("min:"+min);
22.     }

2.找到数组中第一个不重复出现的整数

  1. 用数组存储每个数字出现的次数,但题目只需要找到第一个不重复出现的数,故浪费空间,O(N^2)
  2. 双循环,找到第一个不重复,即返回,O(N^2)

编码1:

1. /**

2. 找出数组中第一个不重复的数字,如果没有就返回null
3. */
4. public class FirstDupNum {
5. @Test
6. public void start() {
7.     int [] arr ={1,2,3,9,7,66,5,5,4,66,3,7,2,9,0,0,1,4};
8.     System.out.println(handler(arr));
9. }
10. public Integer handler(int [] arr){
11.     Integer position=null;
12.     for (int i = 0; i < arr.length; i++) {
13.         for (int j =0; j <arr.length ; j++) {
14.             if(i!=j&&arr[i]==arr[j]){
15.                 position=j;
16.                 break;
17.             }
18.             if(j==arr.length-1){
19.                 position=arr.length;
20.             }
21.         }
22.         if(position==arr.length){
23.             return arr[i];
24.         }
25.     }
26.     return null;
27. }
28. }
29. 编码2:
30. /**

31. 找出数组中第一个不重复的数字 
32. */
33. #define Length(arr) (sizeof(arr)/sizeof(int))
34.  void main() {
35.     int  arr[18] ={1,2,3,9,7,66,5,5,4,8,3,7,2,9,0,0,1,4};    
36.  handler(&arr,Length(arr));

37. }

38. 

39. int handler(int *arr,int length){

for (int i = 0; i < length; i++) {
    int count = 0;
    for (int j = 0; j < length ; j++) {
        if(i!=j&&arr[i]==arr[j]){
            count++;
            break;
        }
     
    }
    if(count==0){
        print("%d",arr[i]);
        break;
    }
}
return 0;
}
}

3.合并两个有序数组

给定两个有序整数数组 nums1 和 nums2,将 nums2 合并到 nums1 中,使得 num1 成为一个有序数组。

示例:

  • nums1 = [1,2,3,0,0,0], m = 3
  • nums2 = [2,5,6], n = 3
  • 输出: [1,2,2,3,5,6]

方法一:合并后,七大排序
这个方法有点生硬,我将nums2数组拷贝到nums1后面,然后得到一个无顺序的数组,这个时候我们学过的七大排序就派上用场了,这里我采用插入排序为例子:

1. class Solution {
2.     public  void merge(int[] nums1, int m, int[] nums2, int n) {
3.         if (n == 0){
4.             return;
5.         }
6.         for (int i = 0; i < nums2.length; i++) {
7.             nums1[m + i] = nums2[i];
8.         }
9.         insertSort(nums1,m + n);
10.     }
11.     public  void insertSort(int[] array,int length){
12.         //这是插入排序
13.         for (int bound = 1; bound < length; bound++) {
14.             int tmp = array[bound];
15.             int cur = bound - 1;
16.             for(;cur >=0;cur--){
17.                 if (array[cur] > tmp){
18.                     array[cur + 1] = array[cur];
19.                 }else {
20.                     break;
21.                 }
22.             }
23.             array[cur + 1] = tmp;
24.         }
25.     }
26. }

时间复杂度:O(N^2)
空间复杂度:O(1)

方法二:合并后排序
arraycopy(Object src, int srcPos, Object dest, int destPos, int length)
Copies an array from the specified source array, beginning at the specified position, to the specified position of the destination array.
意思是,将src数组拷贝到dest目标数组,从0(srcPos)开始拷贝,拷贝到目标数组从m(destPos)开始拷贝,拷n这么长

1. public  void merge(int[] nums1, int m, int[] nums2, int n) {
2.         System.arraycopy(nums2,0,nums1,m,n);
3.         Arrays.sort(nums1);//排序
4.     }

方法三:双指针法
这个方法有点类似合并两个有序链表
也是用两个指针,一个指向nums1(Copy),一个指向nums2,比较大小然后放入nums1中
具体实现代码如下:

1.  public  void merge(int[] nums1, int m, int[] nums2, int n) {
2.         int[] nums1Copy = new int[m];
3.         //将nums1新拷贝一份
4.         System.arraycopy(nums1,0,nums1Copy,0,m);

        //两个指针,一个指向nums1Copy,一个指向nums2
        int p1 = 0;
        int p2 = 0;
        
        int p = 0;//指向nums1最终要输出的
        while ((p1 < m) && (p2 < n)){
            nums1[p++] = (nums1Copy[p1] < nums2[p2])? nums1Copy[p1++] : nums2[p2++];
        }
        if (p1 < m)
            System.arraycopy(nums1Copy, p1, nums1, p, m - p1);
        if (p2 < n)
            System.arraycopy(nums2, p2, nums1, p ,n - p2);
    }

4.重新排列数组中的正值和负值

给定一个包含正数和负数的整数数组,重新排列它,使得所有的负数排在前面,所有的正数排在后面。正数间和负数间的相对顺序保持不变。期望时间复杂度是O(n), 空间复杂度是O(1).

例如: 给定 [-1,2,-2,3,5,-4], 重新排列后变成 [-1,-2,-4,2,3,5]

分析:

  1. 最简单的算法是O(n^2), 遇到每个负数都把它移动到数组前面已经排列好的负数部分后面。
  2. O(n)的算法暂时没想出来,似乎比较难,下面给出一个O(nlogn)的算法。基本思想类似于Merge Sort. 空间复杂度由于用到递归,是O(logn). 不过可以很容易改写为bottom-up的迭代版本。

编码:

1. 
   void Main()
2. {
3.  int[] nums = new int[] {-1, 2, -2, 3, 5, -4};
4.  
5.  Reorder(nums, 0, nums.Length-1);
6. }
7.  
8. *// Define other methods and classes here*
9. public void Reorder(int[] nums, int start, int end)
10. {
11.     if(start >= end) {
12.         return;
13.     }
14.     
15.     int middle = start + (end-start)/2;
16.     Reorder(nums, start, middle);
17.     Reorder(nums, middle+1, end);
18.     Merge(nums, start, middle, end);
19. }
20.  
21. private void Merge(int[] nums, int start, int end)
22. {
23.     int i = start;
24.     while(nums[i] < 0 && i <= end) i++;
25.     int j = end;
26.     while(nums[j] >= 0 && j >= start) j--;
27.     
28.     *// Shift the negative part to the front*
29.     if(i < j) {
30.        int k = j;
31.        while(k>=i && nums[k]<0) k--;
32.        
33.        Reverse(nums, i, k);
34.        Reverse(nums,k+1,j);
35.        Reverse(nums,i,j);
36.     }
37. }
38.  
39. private void Swap(int[] nums, int i, int j)
40. {
41.     int t = nums[i];
42.     nums[i] = nums[j];
43.     nums[j] = t;
44. }
45.  
46. private void Reverse(int[] nums, int i, int j)
47. {
48.     while(i < j) {
49.         Swap(nums, i, j);
50.         i++;
51.         j--;
52.     }
53. }

下面是自底向上的迭代版本。空间复杂度是O(1)。

1. 
   public void Reorder(int[] nums)
2. {
3.     int n = nums.Length;
4.  
5.  for(int size = 1; size < n; size += size)
6.  {
7.      for(int low = 0; low < n-size; low+=size+size)
8.      {
9.          Merge(nums, low, Math.Min(low+size+size-1, n-1));
10.         }
11.     }
12. }

总结:

上面所述就是常常被问到的数据结构的数组面试题;后续还有算法、数据结构、Java面试、Android面试题。,我最近整理了许多,里面讲解的非常详细。领取《Android精选面经题纲》
https://docs.qq.com/doc/DUmVBQXNjdlBDTFNGAndroid精选面经题纲。
咱们下期见!

相关文章

  • 每日一刷“面试题”,面试必过!之数据结构:数组(3)

    想要面试过的去,必须每日一刷题! 关于Android面试这里我就不多讲了,直接上题。 面试题: 1.寻找数组中第二...

  • 2020-01-19做些js的数组练习吧

    1.前端面试必问之数组去重 前端面试必问之数组去重 2.前端面试必问之深拷贝浅拷贝 3.

  • 面试材料

    面试经验 面试题1 面试题2 面试题3 面试题4 面试题5 面试题6――数据结构 面试题7――网络 面试题8――汇...

  • 剑指offer面试题分类总结

    数组: 面试题3:数组中重复的数字面试题4:二维数组中的查找面试题21:调整数组顺序使奇数位于偶数前面面试题39:...

  • 每日一刷“面试题”,面试必过!之网络篇(1)

    想要面试过的去,必须每日一刷题! 关于Android面试这里我就不多讲了,直接上题。 一、面试题: 网络型 1、常...

  • 面试准备——ArrayList、Linked原理与比较

    从一个面试题开始: 数组 像这种面试题,基本都是考察数据结构和算法的知识。所以我们需要先从数据结构开始说起在jav...

  • 剑指offer阅读(一)

    数据结构 面试题二: 数组 数组是一种最简单的数据结构,占据一块连续的数据结构并按照顺序存储数据。创建数组时,我们...

  • 剑指offer

    面试题3——数组中重复的数字 使用LinkedHashMap,有序存放。 面试题4——二维数组中的查找 首先选...

  • 剑指offer目录

    目录 面试题3 在二维数组中查找 面试题15 链表中倒数第K个数 面试题16 反转链表 面试题44 扑克牌的顺子

  • JAVA线程面试题书目录

    JAVA线程面试题之1) 什么是线程? JAVA线程面试题之2) 线程和进程有什么区别? JAVA线程面试题之3)...

网友评论

    本文标题:每日一刷“面试题”,面试必过!之数据结构:数组(3)

    本文链接:https://www.haomeiwen.com/subject/wphjurtx.html