Android面试题(一)Java高频面试题
Android面试题(二)Android中高级/资深面试题
Android面试题(三)Java虚拟机原理面试题
Android面试题(四)常用设计模式面试题
Android面试题(五)数据结构/算法面试题
Android面试题(六)高频网络基础面试题
Android面试题(七)Kotlin高频面试题
Android面试题(八)Flutter高频面试题
目录
一、前言:
算法对于面试者来说是属于比较难的一块了,感觉难的原因主要有如下两方面:
首先:在实际开发中,一般比较少涉及到算法的相关业务开发,除非是做算法这块的,所以就导致算法这块的实际开发经验不是很丰富,需要临时抱佛脚。
其次:算法涉及到的范围比较广,包含字符串、数组、队列、栈、链表、二叉树、排序、堆、图等多种数据结构的算法。
所以说,如果说对算法不是很熟悉,确实需要花费较多的时间去复习,但复习需要有个重点,一般面试频率比较高的一般就是数组、链表、二叉树、排序题这块。需要来重点复习。
这里推荐一下两个刷算法题神器:
上面的题多刷一刷(可以先从easy题目开始刷),等你真的刷出来比较爽感觉来了,那就应该差不多了,O(∩_∩)O哈哈~,去面试大厂的时候你也不用怕了。
这里总结了一些面试频率较高的算法题,大家可以重点参考下,顺便找一下算法题的规律:
二、数组:
-
只出现一次的数字:
给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。
如定义数组:int[] nums = {2, 2, 3, 1, 3} 返回 1 。
public static int singleNumber(int[] nums) {
int res = 0;
for (int num: nums) {
res = res ^ num;
}
return res;
}
-
两数之和:
- 给定一个整数数组和一个目标值,找出组中和为目标值的两个数的位置。
可以假设每个输入只对应一种答案,且同样的元素不能被重复利用。
- 给定一个整数数组和一个目标值,找出组中和为目标值的两个数的位置。
/**
* 方法一>>>>暴力法:
* 时间复杂度:O(n2)
* 空间复杂度:O(1)
* @param numbs
* @param target
* @return
*/
public static int[] twoSum(int[] numbs, int target) {
for (int i = 0; i < numbs.length; i++) {
for (int j = i + 1; j < numbs.length; j++) {
if (numbs[i] + numbs[j] == target) {
return new int[]{i, j};
}
}
}
throw new IllegalArgumentException("参数有误");
}
/**
* 方法2:一遍哈希表
* 在进行迭代并将元素插入到表中的同时,我们还会回过头来检查表中是否已经存在当前元素所对应的目标元素。
* 如果它存在,那我们已经找到了对应解,并立即将其返回。
* 时间复杂度:O(n)
* 空间复杂度:O(n)
* @param numbs
* @param target
* @return
*/
public static int[] twoSumUseHashMap(int[] numbs, int target) {
Map<Integer, Integer> hashMap = new HashMap<>();
for (int i = 0; i < numbs.length; i++) {
int temp = target - numbs[i];
if (hashMap.containsKey(temp)) {
return new int[]{hashMap.get(temp), i};
}
hashMap.put(numbs[i], i);
}
throw new IllegalArgumentException("参数有误");
}
-
合并两个有序数组,使合并后的数组依然是有序的:
private static int[] mergeOrderArrays(int[] array1, int[] array2) {
//两个数组的length中取一个最小的值
int minLength = Math.min(array1.length, array2.length);
//合并之后的数组长度
int totalLength = array1.length + array2.length;
int i = 0;
int j = 0;
int[] array = new int[totalLength];
while (i < array1.length && j < array2.length) {
if (array1[i] <= array2[j]) {
/**
* 判断i是否是该数组最后一个index:
* 如果不是,则继续走原有逻辑(i++)
* 如果是,则走新逻辑【将最后一个值赋值给新数组,然后将array2中的剩余都放到新数组中】
*/
if (i == array1.length - 1) {
array[i + j] = array1[i];
for (; j <= array2.length - 1; j++) {
array[i + j + 1] = array2[j];
}
break;
} else {
array[i + j] = array1[i++];
}
} else {
if (j == array2.length - 1) {
array[i + j] = array2[j];
for (; i <= array1.length - 1; i++) {
array[i + j + 1] = array1[i];
}
break;
} else {
array[i + j] = array2[j++];
}
}
}
return array;
}
-
顺时针打印矩阵【参考】
输入:matrix = [[1,2,3],[4,5,6],[7,8,9]] 输出:[1,2,3,6,9,8,7,4,5]
public int[] spiralOrder(int[][] matrix) {
int l = 0;
int r = matrix[0].length - 1;
int t = 0;
int b = matrix.length - 1;
int x = 0;
int[] res = new int[matrix.length * matrix[0].length];
while(true) {
//从左到右
for(int i = l; i <= r; i++) res[x++] = matrix[t][i];
if(++t > b) break;
//从上到下
for(int i = t; i <= b; i++) res[x++] = matrix[i][r];
if(--r < l) break;
//从右到左
for(int i = r; i >= l; i--) res[x++] = matrix[b][i];
if(--b < t) break;
//从下到上
for(int i = b; i>= t; i--) res[x++] = matrix[i][l];
if(++l > r) break;
}
return res;
}
三、字符串:
-
返回最长不含重复字符的子字符串长度:
方法1:双循环
public int lengthOfLongestSubstring (String s) {
int max = 1;
int temp = 1;
char[] chars = s.toCharArray();
HashSet<Character> hashSet = new HashSet<Character>();
for (int i = 0; i < chars.length; i++) {
temp = 1;
hashSet.clear();
for (int j = i + 1; j < chars.length; j++) {
if (chars[i] != chars[j] && !hashSet.contains(chars[j])) {
hashSet.add(chars[j]);
temp++;
if(temp > max) {
max = temp;
}
} else {
break;
}
}
}
return max;
}
方法2:双指针
/**
* 方法二:
* 双指针
*/
public static int longestSubStr_Two(String s) {
//结果变量
int result = 0;
int len = s.length();
//set集合用来判断子字符串是否包含重复元素
Set<Character> hashSet = new HashSet<>();
//j指针即结束位置指针初值应该为0
int j = 0;
for (int i = 0; i < len; i++) {
if (i != 0) {
//每次遍历新的起始位置,都要把前面的元素从集合中移出。
hashSet.remove(s.charAt(i - 1));
}
//向后移动j指针,直到遇到字符串结尾或者将要包含重复元素为止
while (j < len && !hashSet.contains(s.charAt(j))) {
//当添加下一个元素,仍不包含重复元素时,可以添加进行,并把j指针后移
hashSet.add(s.charAt(j));
j++;
}
//更新结果变量
result = Math.max(result, j - i);
}
return result;
}
四、链表:
-
删除无序单链表中重复的节点
/**
* 方法1:利用哈希表:
* 如果HashSet中不包含当前节点的值,则存入HashSet中,后移一位继续判断;如果包含,则将前一节点的next值指向当前节点的next值(即删除当前节点)。
*/
public static Node doRemoveRepeatNode1(Node head) {
Node pre;
Node cur;
if (head == null) {
return null;
}