今日面试
1、冒泡排序
- #include <stdio.h>
- void swap(int *a, int *b);
- int main()
- {
- int array[10] = {15, 225, 34, 42, 52, 6, 7856, 865, 954, 10};
- int i, j;
- for (i = 0; i < 10; i++)
- {
- //每一次由底至上地上升
- for (j = 9; j > i; j--)
- {
- if (array[j] < array[j-1])
- {
- swap(&array[j], &array[j-1]);
- }
- }
- }
- for (i = 0; i < 10; i++)
- {
- printf("%d\n", array[i]);
- }
- return 0;
- }
- void swap(int *a, int *b)
- {
- int temp;
- temp = *a;
- *a = *b;
- *b = temp;
- }
冒泡排序算法只会将较少的逐步向上推,不会造成文章前面所说的不足,这里就不给予演示。
07-12
求两个有序数组的中位数-算法导论
Question
There are 2 sorted arrays A and B of size n each. Write an algorithm to find the median of the array obtained after merging the above 2 arrays(i.e. array of length 2n). The complexity should be O(log(n))。
有两个排序的数组,长度都为n,求合并后的排序数组的中位数。
题目是《算法导论》上的一道习题,不过已多次出现在面试题当中。注意,此题中两个数组的长度是相等的。当然,长度不等的话也可以做,只是要多些判断条件。参考leetcode题目 Median of Two Sorted Arrays
方法1 直接遍历
直接的解法是遍历两个数组并计数,类似归并排序里面的有序数组的合并,复杂度为O(n)。代码如下:
01 |
#include <iostream> |
02 |
#include <stdio.h> |
03 |
using namespace std; |
04 |
05 |
double getMedian( int arr1[], int arr2[], int n){ |
06 |
int i=0,j=0; //分别是 arr1, arr2的当前下标 |
07 |
int m1=-1,m2=-1; //保存两个中位数. 由于是2n个,肯定有两个中位数 |
08 |
for ( int cnt=0; cnt<=n; cnt++){ |
09 |
if ( i<n && (arr1[i] < arr2[j] || j >= n )){ |
10 |
m1 = m2; |
11 |
m2 = arr1[i++]; |
12 |
} else { |
13 |
m1 = m2; |
14 |
m2 = arr2[j++]; |
15 |
} |
16 |
} |
17 |
return (m1+m2)/2.0; |
18 |
} |
19 |
int main() |
20 |
{ |
21 |
int ar1[] = {1, 12, 15, 26, 38}; |
22 |
int ar2[] = {2, 13, 17, 30, 45}; |
23 |
24 |
int n1 = sizeof (ar1)/ sizeof (ar1[0]); |
25 |
int n2 = sizeof (ar2)/ sizeof (ar2[0]); |
26 |
if (n1 == n2) |
27 |
printf ( "Median is %lf" , getMedian(ar1, ar2, n1)); |
28 |
else |
29 |
printf ( "Doesn't work for arrays of unequal size" ); |
30 |
return 0; |
31 |
} |
方法2 分治法
要求的复杂度为O(log (m+n)),很显然需要用分治法求解。
假设数组A的中位数为m1,数组B为m2,例如:
ar1[] = {1, 12, 15, 26, 38}
ar2[] = {2, 13, 17, 30, 45}
m1 = 15 ,m2 = 17 。由于m1<m2,则可以确定中位数即为下面两个子数组的中位数 :
[15, 26, 38] 和 [2, 13, 17]
重复这个步骤,可以得到 m1 = 26 m2 = 13. 得到两个子数组:
[15, 26] 和[13, 17]
这时,由于n=2,无法在继续分下去了。可以直接计算得:
1 |
median = (max(ar1[0], ar2[0]) + min(ar1[1], ar2[1]))/2 |
2 |
= (max(15, 13) + min(26, 17))/2 |
3 |
= (15 + 17)/2 |
4 |
= 16 |
代码如下:
01 |
int median( int arr[], int n) |
02 |
{ |
03 |
if (n%2 == 0) |
04 |
return (arr[n/2] + arr[n/2-1])/2; |
05 |
else |
06 |
return arr[n/2]; |
07 |
} |
08 |
09 |
int getMedian( int ar1[], int ar2[], int n) { |
10 |
int m1; |
11 |
int m2; |
12 |
if (n <= 0) |
13 |
return -1; |
14 |
if (n == 1) |
15 |
return (ar1[0] + ar2[0]) / 2; |
16 |
17 |
if (n == 2) |
18 |
return (max(ar1[0], ar2[0]) + min(ar1[1], ar2[1])) / 2; |
19 |
20 |
m1 = median(ar1, n); |
21 |
m2 = median(ar2, n); |
22 |
/* 相等可直接返回 */ |
23 |
if (m1 == m2) |
24 |
return m1; |
25 |
if (m1 < m2) { |
26 |
if (n % 2 == 0) |
27 |
return getMedian(ar1 + n/2-1, ar2, n/2 + 1); |
28 |
else |
29 |
return getMedian(ar1 + n/2, ar2, n/2+1); |
30 |
} else { |
31 |
if (n % 2 == 0) |
32 |
return getMedian(ar2 + n/2-1, ar1, n/2+1); |
33 |
else |
34 |
return getMedian(ar2 + n/2, ar1, n/2+1); |
35 |
} |
36 |
} |
37 |
38 |
int main() |
39 |
{ |
40 |
int ar1[] = {1, 12, 10, 26, 38}; |
41 |
int ar2[] = {2, 13, 17, 30, 45}; |
42 |
43 |
int n1 = sizeof (ar1)/ sizeof (ar1[0]); |
44 |
int n2 = sizeof (ar2)/ sizeof (ar2[0]); |
45 |
if (n1 == n2) |
46 |
printf ( "Median is %d" , getMedian(ar1, ar2, n1)); |
47 |
else |
48 |
printf ( "Doesn't work for arrays of unequal size" ); |
49 |
return 0; |
50 |
} |
时间复杂度为 O(logn)。
重写(覆盖)的规则:
1、重写方法的参数列表必须完全与被重写的方法的相同,否则不能称其为重写而是重载.
2、重写方法的访问修饰符一定要大于被重写方法的访问修饰符(public>protected>default>private)。
3、重写的方法的返回值必须和被重写的方法的返回一致;
4、重写的方法所抛出的异常必须和被重写方法的所抛出的异常一致,或者是其子类;
5、被重写的方法不能为private,否则在其子类中只是新定义了一个方法,并没有对其进行重写。
重载的规则:
1、在使用重载时只能通过相同的方法名、不同的参数形式实现。不同的参数类型可以是不同的参数类型,不同的参数个数,不同的参数顺序(参数类型必须不一样);
2、不能通过访问权限、返回类型、抛出的异常进行重载;
3、方法的异常类型和数目不会对重载造成影响;
一般,我们使用多态是为了避免在父类里大量重载引起代码臃肿且难于维护。
Java中对Array数组的常用操作
目录:
- 声明数组;
- 初始化数组;
- 查看数组长度;
- 遍历数组;
- int数组转成string数组;
- 从array中创建arraylist;
- 数组中是否包含某一个值;
- 将数组转成set集合;
- 将数组转成list集合;
- Arrays.fill()填充数组;
- 数组排序;
- 复制数组;
- 比较两个数组;
- 去重复;
- 查询数组中的最大值和最小值;
备注:文内代码具有关联性。
1.声明数组;
1
2
3
4
|
String [] arr; int arr1[]; String[] array= new String[ 5 ]; int score[]= new int [ 3 ]; |
2.初始化数组;
1
2
3
4
5
6
7
8
9
10
|
//静态初始化 int arr2[]= new int []{ 1 , 2 , 3 , 4 , 5 }; String[] array1={ "马超" , "马云" , "关羽" , "刘备" , "张飞" }; String[] array2= new String[]{ "黄渤" , "张艺兴" , "孙红雷" , "小猪" , "牙哥" , "黄磊" }; int score[]= new int [ 3 ]; //动态初始化 for ( int i= 0 ;i<score.length;i++) { score[i]=i+ 1 ; } |
3.查看数组长度;
1
2
|
int length=array1.length; System.out.println( "length: " +array1.length); |
4.遍历数组;
1
2
3
|
for ( int i = 0 ; i < array1.length; i++) { System.out.println(array1[i]); } |
5.int数组转成string数组;
1
2
3
|
int [] array3={ 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 0 }; String arrStrings=Arrays.toString(array3); System.out.println(arrStrings); |
6.从array中创建arraylist;
1
2
|
ArrayList<String> arrayList= new ArrayList<String>(Arrays.asList(array1)); System.out.println(arrayList); |
7.数组中是否包含某一个值;
1
2
3
4
5
|
String a= "马超" ; String[] array1={ "马超" , "马云" , "关羽" , "刘备" , "张飞" }; if (Arrays.asList(array1).contains(a)) { System.out.println( "马超在这里" ); } |
8.将数组转成set集合;
1
2
3
|
String[] array2= new String[]{ "黄渤" , "张艺兴" , "孙红雷" , "小猪" , "牙哥" , "黄磊" }; Set<String> set= new HashSet<String>(Arrays.asList(array2)); System.out.println(set); |
9.将数组转成list集合;
1
2
3
4
5
6
7
8
9
10
11
|
String[] array2= new String[]{ "黄渤" , "张艺兴" , "孙红雷" , "小猪" , "牙哥" , "黄磊" }; //方法 1. List<String> list= new ArrayList<String>(); for ( int i = 0 ; i < array2.length; i++) { list.add(array2[i]); } String[] arrStrings2={ "1" , "2" , "3" }; //方法 2. List<String > list2=java.util.Arrays.asList(arrStrings2); System.out.println(list2); |
10.Arrays.fill()填充数组;
1
2
3
4
5
6
|
int [] arr3= new int [ 5 ]; Arrays.fill(arr3, 10 ); //将数组全部填充10 //遍历输出 for ( int i = 0 ; i < arr3.length; i++) { System.out.println(arr3[i]); } |
11.数组排序;
1
2
3
4
5
6
7
8
9
10
11
12
|
//方法 1. int [] arr4 = { 3 , 7 , 2 , 1 , 9 }; Arrays.sort(arr4); //.sort(int[] a) 放入数组名字 for ( int i = 0 ; i < arr4.length; i++) { System.out.println(arr4[i]); } //方法 2. int [] arr5 = { 3 , 7 , 2 , 1 , 9 , 3 , 45 , 7 , 8 , 8 , 3 , 2 , 65 , 34 , 5 }; Arrays.sort(arr5, 1 , 4 ); //.sort(a, fromIndex, toIndex) 从第几个到第几个之间的进行排序 for ( int i = 0 ; i < arr5.length; i++) { System.out.println(arr5[i]); } |
12.复制数组;
1
2
3
4
5
6
7
8
|
//方法 1. int [] arr6 = { 3 , 7 , 2 , 1 }; int [] arr7=Arrays.copyOf(arr6, 10 ); //指定新数组的长度 //方法 2. int [] arr8=Arrays.copyOfRange(arr6, 1 , 3 ); //只复制从索引[1]到索引[3]之间的元素(不包括索引[3]的元素) for ( int i = 0 ; i < arr8.length; i++) { System.out.println(arr8[i]); } |
13.比较两个数组;
1
2
3
|
int [] arr9 = { 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 0 }; boolean arr10=Arrays.equals(arr6, arr9); System.out.println(arr10); |
14.去重复;
1
2
3
4
5
6
7
8
9
10
11
12
13
|
int [] arr11 = { 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 0 , 3 , 2 , 4 , 5 , 6 , 7 , 4 , 32 , 2 , 1 , 1 , 4 , 6 , 3 }; //利用set的特性 Set<Integer> set2= new HashSet<Integer>(); for ( int i = 0 ; i < arr11.length; i++) { set2.add(arr11[i]); } System.out.println(set2); int [] arr12 = new int [set2.size()]; int j= 0 ; for (Integer i:set2) { arr12[j++]=i; } System.out.println(Arrays.toString(arr12)); |
15.查询数组中的最大值和最小值;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
int [] arr11 = { 10 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 0 , 3 , 2 , 4 , 5 , 6 , 7 , 4 , 32 , 2 , 1 , 1 , 4 , 6 , 3 }; //计算最大值 int max = arr11[ 0 ]; for ( int i = 1 ; i < arr11.length; i++) { if (arr11[i] > max) { max = arr11[i]; } } System.out.println( "Max is " + max); //计算最小值 int min = arr11[ 0 ]; for ( int i = 0 ; i < arr11.length; i++) { if (arr11[i]<min) { min = arr11[i]; } } System.out.println( "Min is " + min); |