day26
剑指 Offer 03. 数组中重复的数字
题目
找出数组中重复的数字。
在一个长度为 n 的数组 nums 里的所有数字都在 0~n-1 的范围内。数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。请找出数组中任意一个重复的数字。
示例 1:
输入:
[2, 3, 1, 0, 2, 5, 3]
输出:2 或 3
思路
要求时间复杂度 O(N),空间复杂度 O(N)。因此不能使用排序的方法,也不能使用额外的标记数组。
对于这种数组元素在 [0, n-1] 范围内的问题,可以将值为 i 的元素调整到第 i 个位置上进行求解。在调整过程中,如果第 i 位置上已经有一个值为 i 的元素,就可以知道 i 值重复。
以 (2, 3, 1, 0, 2, 5) 为例,遍历到位置 4 时,该位置上的数为 2,但是第 2 个位置上已经有一个 2 的值了,因此可以知道 2 重复:
代码实现
/**
* https://leetcode-cn.com/problems/shu-zu-zhong-zhong-fu-de-shu-zi-lcof/
*
* @author xiexu
* @create 2022-04-18 22:59
*/
public class _剑指Offer03_数组中重复的数字 {
public int findRepeatNumber(int[] nums) {
for (int i = 0; i < nums.length; i++) {
while (nums[i] != i) {
if (nums[i] == nums[nums[i]]) {
return nums[i];
}
swap(nums, i, nums[i]);
}
}
return -1;
}
private void swap(int[] nums, int i, int j) {
int t = nums[i];
nums[i] = nums[j];
nums[j] = t;
}
}
剑指 Offer 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
。
限制:
0 <= n <= 1000
0 <= m <= 1000
思路
要求时间复杂度 O(M + N),空间复杂度 O(1)。其中 M 为行数,N 为 列数。
该二维数组中的一个数,小于它的数一定在其左边,大于它的数一定在其下边。因此,从右上角开始查找,就可以根据 target 和当前元素的大小关系来快速地缩小查找区间,每次减少一行或者一列的元素。当前元素的查找区间为左下角的所有元素。
代码实现
/**
* https://leetcode-cn.com/problems/er-wei-shu-zu-zhong-de-cha-zhao-lcof/
*
* @author xiexu
* @create 2022-04-18 22:34
*/
public class _剑指Offer04_二维数组中的查找 {
public boolean findNumberIn2DArray(int[][] matrix, int target) {
if (matrix == null || matrix.length == 0 || matrix[0].length == 0) {
return false;
}
// 行
int row = matrix.length;
// 列
int col = matrix[0].length;
int r = 0, c = col - 1; // 从右上角开始
while (r <= row - 1 && c >= 0) {
if (target == matrix[r][c]) {
return true;
} else if (target > matrix[r][c]) {
r++; // 往下一行查找
} else { // target < matrix[r][c]
c--; // 往左边查找
}
}
return false;
}
}
剑指 Offer 05. 替换空格
题目
请实现一个函数,把字符串 s
中的每个空格替换成"%20"。
示例 1:
输入:s = "We are happy."
输出:"We%20are%20happy."
限制:
0 <= s 的长度 <= 10000
代码实现
/**
* https://leetcode-cn.com/problems/ti-huan-kong-ge-lcof/
*
* @author xiexu
* @create 2022-04-18 23:10
*/
public class _剑指Offer05_替换空格 {
public String replaceSpace(String s) {
if (s == null) {
return null;
}
StringBuilder sb = new StringBuilder();
for (int i = 0; i < s.length(); i++) {
if (s.charAt(i) == ' ') {
sb.append("%20");
} else {
sb.append(s.charAt(i));
}
}
return sb.toString();
}
}
剑指 Offer 29. 顺时针打印矩阵
题目
输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字。
示例 1:
输入:matrix = [[1,2,3],[4,5,6],[7,8,9]]
输出:[1,2,3,6,9,8,7,4,5]
示例 2:
输入:matrix = [[1,2,3,4],[5,6,7,8],[9,10,11,12]]
输出:[1,2,3,4,8,12,11,10,9,5,6,7]
限制:
0 <= matrix.length <= 100
0 <= matrix[i].length <= 100
思路
一层一层从外到里打印,观察可知每一层打印都有相同的处理步骤,唯一不同的是上下左右的边界不同了。因此使用四个变量 r1, r2, c1, c2 分别存储上下左右边界值,从而定义当前最外层。打印当前最外层的顺序:从左到右打印最上一行->从上到下打印最右一行->从右到左打印最下一行->从下到上打印最左一行。应当注意只有在 r1 != r2 时才打印最下一行,也就是在当前最外层的行数大于 1 时才打印最下一行,这是因为当前最外层只有一行时,继续打印最下一行,会导致重复打印。打印最左一行也要做同样处理。
代码实现
/**
* https://leetcode-cn.com/problems/shun-shi-zhen-da-yin-ju-zhen-lcof/
*
* @author xiexu
* @create 2022-04-18 23:23
*/
public class _剑指Offer29_顺时针打印矩阵 {
public int[] spiralOrder(int[][] matrix) {
int m = matrix.length; // 行
if (m == 0) {
return new int[0];
}
int n = matrix[0].length; // 列
int[] res = new int[m * n];
int index = 0;
// r1,r2表示上下
int r1 = 0, r2 = m - 1;
// c1,c2表示左右
int c1 = 0, c2 = n - 1;
while (r1 <= r2 && c1 <= c2) {
// 上
for (int i = c1; i <= c2; i++) {
res[index++] = matrix[r1][i];
}
// 右
for (int i = r1 + 1; i <= r2; i++) {
res[index++] = matrix[i][c2];
}
// 下
if (r1 != r2) {
for (int i = c2 - 1; i >= c1; i--) {
res[index++] = matrix[r2][i];
}
}
// 左
if (c1 != c2) {
for (int i = r2 - 1; i > r1; i--) {
res[index++] = matrix[i][c1];
}
}
r1++;
r2--;
c1++;
c2--;
}
return res;
}
}
剑指 Offer 50. 第一个只出现一次的字符
题目
在字符串 s 中找出第一个只出现一次的字符。如果没有,返回一个单空格。 s 只包含小写字母。
示例 1:
输入:s = "abaccdeff"
输出:'b'
示例 2:
输入:s = ""
输出:' '
限制:
0 <= s 的长度 <= 50000
代码实现
/**
* https://leetcode-cn.com/problems/di-yi-ge-zhi-chu-xian-yi-ci-de-zi-fu-lcof/
*
* @author xiexu
* @create 2022-04-19 00:12
*/
public class _剑指Offer50_第一个只出现一次的字符 {
public char firstUniqChar(String s) {
char[] words = new char[26];
for (int i = 0; i < s.length(); i++) {
words[s.charAt(i) - 'a']++;
}
for (int i = 0; i < s.length(); i++) {
if (words[s.charAt(i) - 'a'] == 1) {
return s.charAt(i);
}
}
return ' ';
}
}