一、二维数组的查找
题目描述
在一个二维数组中(每个一维数组的长度相同),
每一行都按照从左到右递增的顺序排序,
每一列都按照从上到下递增的顺序排序。
请完成一个函数,输入这样的一个二维数组和一个整数,
判断数组中是否含有该整数。
思路
从右上开始往左下找,
如果大于target,就排除当前列,因为target(小)一定不在右边也不在下面,而是在左边,所以把列数col减一
如果小于target,就排除当前行,因为target(大)一定不在左边,只能在右边或者下面,并把行数row加一
综上,时间复杂度:O(行高 + 列宽)
空间复杂度:O(1)
代码
public class Solution {
public boolean Find(int target, int [][] array) {
int rows = array.length;
int cols = array[0].length;
if (rows == 0)
return false ;
if (cols == 0)
return false ;
int row = 0;
int col = cols - 1;
while (row < rows && col >= 0){
if (array[row][col] == target)
return true ;
else if (array[row][col] < target)
col--;
else
row++;
}
return false ;
}
}
二、数组中重复的数字
题目描述
在一个长度为n的数组里的所有数字都在0到n-1的范围内。
数组中某些数字是重复的,但不知道有几个数字是重复的。
也不知道每个数字重复几次。请找出数组中任意一个重复的数字。
例如,如果输入长度为7的数组{2,3,1,0,2,5,3},
那么对应的输出是第一个重复的数字2。
思路一
先排序,若左边和右边的数字相等,则返回该值
时间复杂度:O(nlogn)
空间复杂度:O(1)
代码
import java.util.*;
public class Solution {
public boolean duplicate(int numbers[],int length,int [] duplication) {
if (numbers == null || length == 0)
return false ;
Arrays.sort(numbers);
for (int i = 0; i < length-1; i++){
if (numbers[i] == numbers[i+1]){
duplication[0] = numbers[i];
return true ;
}
}
return false ;
}
}
思路二
利用HashSet,按顺序判断是否有重复,有就输出
时间复杂度:O(n)
空间复杂度:O(n)
代码
import java.util.*;
public class Solution {
public boolean duplicate(int numbers[],int length,int [] duplication) {
if (numbers == null || length == 0)
return false ;
Set<Integer> set = new HashSet<>();
for (int i = 0; i < length; i++){
if (set.contains(numbers[i])){
duplication[0] = numbers[i];
return true ;
}
else
set.add(numbers[i]);
}
return false ;
}
}
思路三
利用特性
时间复杂度:O(n)
空间复杂度:O(1)
代码
三、构建乘积数组
题目描述
给定一个数组A[0,1,...,n-1],请构建一个数组B[0,1,...,n-1],
其中B中的元素B[i]=A[0]A[1]...A[i-1]A[i+1]...A[n-1]。
不能使用除法。
思路
先计算左边的下三角的每一行
后把右边,从倒数第二行开始(倒数第一行已为结果),每次循环乘一个A[i]
时间复杂度:O(n)
空间复杂度:O(n)
代码
class Solution {
public int[] constructArr(int[] a) {
int len = a.length;
if (a == null || len == 0)
return a;
int[] B = new int[len];
B[0] = 1;
for (int i =1; i < len; i++){
B[i] = B[i-1] * a[i-1];
}
int temp = 1;
for (int j = len-1; j >= 0; j--){
//B[3],长度为4,最后一个已经确定,所以从B[2]开始,所以是长度减2
B[j] *= temp;
temp *= a[j];
//B[1],j=1,
}
return B;
}
}
四、在排序数组中查找数字 I
题目描述
统计一个数字在排序数组中出现的次数。
思路
有序->二分查找
找到之后,left往前倒数,right往后加,得到的总步数就是次数
时间复杂度:O(logn)
空间复杂度:O(1)
代码
class Solution {
public int search(int[] nums, int target) {
//有序一定要想到二分
int index=find(nums,target);
int left=index;
int right=index+1;
int count=0;
while (left>=0&&nums[left]==target){
count++;
left--;
}
while (right<nums.length&&nums[right]==target){
count++;
right++;
}
return count;
}
public int find(int[] nums, int target){
int left=0;
int mid;
int right=nums.length-1;
while (left<=right){
mid=(left+right)/2;
if (nums[mid]>target){
right=mid-1;
}else if (nums[mid]<target){
left=mid+1;
}else {
return mid;
}
}
return -1;
}
}
五、顺时针打印矩阵
题目描述
输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字。
思路
代码
六、 翻转单词顺序
题目描述
输入一个英文句子,翻转句子中单词的顺序,但单词内字符的顺序不变。
为简单起见,标点符号和普通字母一样处理。
例如输入字符串"I am a student. " ,则输出"student. a am I" 。
思路
代码