前言
本文主要是写了我做算法题的思路以及对其他优秀题解的自我理解。
一、二维数组中的查找
题目
在一个 n * m 的二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个高效的函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。leetcode链接
示例:
现有矩阵 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。
限制:
0 <= n <= 1000
0 <= m <= 1000
题解一
看到此题中的条件:每一行从左到右都是递增的,每一列从上到下也是递增的,因此可以说每一行都是有序的。由此我想到了最近很熟悉的二分查找,所以写出了以下的题解,通过对每一行进行二分查找,如果能找到就返回true,如果每一行都找不到那么就返回false。
public boolean findNumberIn2DArray1(int[][] matrix, int target) {
//边界条件判断
if (matrix == null || matrix.length == 0 ||
matrix[0] == null || matrix[0].length == 0)
return false;
for (int i = 0;i < matrix.length ;i++){
if (Arrays.binarySearch(matrix[i],target) >= 0){
return true;
}else{
continue;
}
}
return false;
}
题解二
暴力查找法:我们之前也做过类似的在数组中查找target的题目,可以直接对数组进行暴力遍历,找到就返回true,找不到返回false。
时间复杂度为O(n*m),空间复杂度为O(1).
public boolean findNumberIn2DArray(int[][] matrix, int target) {
if (matrix == null || matrix.length == 0 || matrix[0].length == 0) {
return false;
}
int rows = matrix.length, columns = matrix[0].length;
for (int i = 0; i < rows; i++) {
for (int j = 0; j < columns; j++) {
if (matrix[i][j] == target) {
return true;
}
}
}
return false;
}
题解三
此题解出自这里
这个二维数组是有特点的:
每一行都是递增的
每一列都是递增的
首先,我们初始化一个指向矩阵右上角的元素 。
从这个元素开始查找,如果这个元素比 target 大,则说明需要找更小的,往左走;如果这个元素比 target 小,则说明应该找更大的,往下走。
此方法的时间复杂度为O(n+m)
public boolean Find(int target, int [][] array) {
//边界条件判断
if (array == null || array.length == 0 ||
array[0] == null || array[0].length == 0)
return false;
//获取函数矩阵的行数 m 与列数 n
int m = array.length, n = array[0].length;
//初始化一开始的元素位置,这里我们设置为矩阵最右上角的元素
int i = 0, j = n - 1;
//循环遍历整个函数
while (i < m && j >= 0) {
//如果目标值小于右上角的数字,则列下标减一
if (target < array[i][j]) j--;
//如果目标值大于右上角的数字,则行下标加一
else if (target > array[i][j]) i++;
//如果相等,直接 true
else return true;
}
//循环结束后如果还没有找到目标时,返回 false
return false;
}
二、替换空格
题目
请实现一个函数,把字符串 s 中的每个空格替换成"%20"。
示例 1:
输入:s = "We are happy."
输出:"We%20are%20happy."
限制:
0 <= s 的长度 <= 10000
题解一
根据题目的描述我第一反应是想到了java中String类的函数replaceAll,使用改方法只需要一行代码直接通过。
public String replaceSpace(String s) {
return s.replaceAll(" ","%20");
}
但是如果面试的时候被问到这样的题目面试官肯定希望你不止会使用java自带的函数解决,还能不使用函数解决。
题解二
String是不可改变的,但是java中也有可变的字符串StringBuilder,初始化一个 StringBuilder 实例 sb,遍历字符串 s 的每个字符,当遍历到非空字符的时候,直接将字符 append 到 sb 中,如果遍历到的是空字符,那么将 %20 append 到 sb 中,然后直接返回 sb.toString。
public String replaceSpace(String s) {
StringBuilder sb = new StringBuilder();
for (char c : s.toCharArray()) {
if (c == ' ') sb.append("%20");
else sb.append(c);
}
return sb.toString();
}
时间复杂度是 O(n) 空间复杂度是 O(n)
题解三
使用自定义数组的方式,创建一定长度的数组,然后遍历原字符串的每一个字符,遇到非空格就放入数组中,遇到空格就把%20依次放入数组中,最后将该数组以字符串返回。
这里有一个关键的问题是:自定义数组的长度该设置为多少呢?
方法一:原字符串长度的三倍(这样会有一部分空间可能用不到)
方法二:在定义数组前,先遍历原字符串计算出空格的数量,然后定义数组的长度为:原字符串长度+空格数*2
方法一:
public String replaceSpace(String s) {
int n = s.length();
char[] newArr = new char[3 * n];
int j = 0;
for (int i = 0; i < n; i++) {
char c = s.charAt(i);
if (c == ' ') {
newArr[j++] = '%';
newArr[j++] = '2';
newArr[j++] = '0';
} else {
newArr[j++] = c;
}
}
return new String(newArr, 0, j);
}
方法二
public String replaceSpace4(String s) {
int n = s.length();
int cnt = 0;
for (char c : s.toCharArray()) {
if (c == ' ') cnt++;
}
char[] newArr = new char[n + 2 * cnt];
int j = 0;
for (int i = 0; i < n; i++) {
char c = s.charAt(i);
if (c == ' ') {
newArr[j++] = '%';
newArr[j++] = '2';
newArr[j++] = '0';
} else {
newArr[j++] = c;
}
}
return new String(newArr);
}