88. 合并两个有序数组
给定两个有序整数数组 nums1 和 nums2,将 nums2 合并到 nums1 中,使得 num1 成为一个有序数组。
说明:
初始化 nums1 和 nums2 的元素数量分别为 m 和 n。
你可以假设 nums1 有足够的空间(空间大小大于或等于 m + n)来保存 nums2 中的元素。
示例:
输入:
nums1 = [1,2,3,0,0,0], m = 3
nums2 = [2,5,6], n = 3输出: [1,2,2,3,5,6]
解析:
1.将nums2的元素往nums1中存
nums1的有效元素个数为 index1 = m-1
nums1的总长度为 index = m+n-1
nums2的长度为 index2 = n-1
2.nums1和nums2从后向前比较
如果nums1[index1] > nums2[index2],则nums1[index--]=nums1[index1--]
如果nums1[index1] <= nums2[index2],则nums1[index--]=nums2[index2--]
当index1<0或者index2<0时循环结束
当index2<0时,说明nums2中的元素已经全部加入nums1
当index1<0时,idenx2>=0时直接将nums2中的元素遍历到nums1中
public void merge(int[] nums1, int m, int[] nums2, int n) {
int index=m+n-1;
int index1=m-1;
int index2=n-1;
while(true){
if(index1<0||index2<0){//跳出循环
break;
}
if(nums1[index1]>=nums2[index2]){
nums1[index--]=nums1[index1--];
}else{
nums1[index--]=nums2[index2--];
}
}
if(index2>=0){
for(int i=0;i<=index2;i++){
nums1[i]=nums2[i];
}
}
}
35. 搜索插入位置
给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。
你可以假设数组中无重复元素。
示例 1:
输入: [1,3,5,6], 5
输出: 2
示例 2:输入: [1,3,5,6], 2
输出: 1
示例 3:输入: [1,3,5,6], 7
输出: 4
示例 4:输入: [1,3,5,6], 0
输出: 0
解析:排序数组,有目标值,类似于二分查找
1.二分查找 low high mid
2.两种特殊情况: ①查找在low ②查找在high
3.正常情况下,查找的元素和mid比较,看在哪边
如果元素=mid时,return mid
如果元素<mid在左,high=mid-1 mid=(low+high)/2
如果元素>mid在右,low=mid+1 mid=(low+high)/2
这就是二分查找
4.当low>high时 没有找到 将元素插入low的位置
public int searchInsert(int[] nums, int target) {
int low=0;
int high=nums.length-1;
int mid=(low+high)/2;
//判断nums是否为空
if(nums==null||nums.length==0){
return 0;
}
//判断查找的元素在low
if(nums[low]==target){
return low;
}
//判断查找的元素在high
if(nums[high]==target){
return high;
}
//当low<=high继续查找,负责没有查到
while(low<=high){
//判断查找的元素在mid
if(nums[mid]==target){
return mid;
}
//右边
if(nums[mid]<target){
low=mid+1;
}else{//左边
high=mid-1;
}
mid=(low+high)/2;
}
return low;
}
66. 加一
给定一个由整数组成的非空数组所表示的非负整数,在该数的基础上加一。
最高位数字存放在数组的首位, 数组中每个元素只存储单个数字。
你可以假设除了整数 0 之外,这个整数不会以零开头。
示例 1:
输入: [1,2,3]
输出: [1,2,4]
解释: 输入数组表示数字 123。
示例 2:输入: [4,3,2,1]
输出: [4,3,2,2]
解释: 输入数组表示数字 4321。
解析:根据题意,加1,有可能产生进制,例如[1,2,9] + 1 = [1,3,0]。当9+1产生进位,存0进去 ,我们可以用(digits[x]+1)%10来判断,那怎么知道是否有进位呢?可以用(digits[x]+1)/10判断,等于10时说明就有进位产生。当然我们也有特殊情况,999+1 变成4位数,[9,9,9] + 1 = [1,0,0,0],定义一个进位carry,来判断当前是不是999,如果carry最后等于1,说明是999
public int[] plusOne(int[] digits) {
int carry=1;//进位
int num=0;
//从数组最后一位开始计算
for(int i=digits.length-1;i>=0;i--){
num=digits[i]+carry;
digits[i]=num%10;//超出10,用取余取出个位存进去
carry=num/10;//num=10,证明产生进位
//无进位
if(carry==0){
break;
}
}
//循环跳出后,carry==1证明是999+1的情况
if(carry==1){
int[] arr = new int[digits.length+1];//创建一个长度为digits.length+1新数组
arr[0]=1;
return arr;
}
return digits;
}
20. 有效的括号
给定一个只包括 '(',')','{','}','[',']' 的字符串,判断字符串是否有效。
有效字符串需满足:
左括号必须用相同类型的右括号闭合。
左括号必须以正确的顺序闭合。
注意空字符串可被认为是有效字符串。
示例 1:
输入: "()"
输出: true
示例 2:输入: "()[]{}"
输出: true
示例 3:输入: "(]"
输出: false
示例 4:输入: "([)]"
输出: false
示例 5:输入: "{[]}"
输出: true
解析:根据题意,我们可以用栈进行判断。将字符串拆分存进数组中,首先判断栈是否为空,如果为空直接存进去;如果不为空,先将其与栈顶元素进行比较,相匹配的符号之间相差-1或-2( top-c ==-1 || top-c==-2),如果匹配将栈顶元素出栈,如果不匹配入栈。
public boolean isValid(String s) {
//创建一个栈
Stack<Character> stack = new Stack<Character>();
//将字符串中的字符拆开放入栈中
for(int i=0;i<s.length();i++){
char c = s.charAt(i);
//判断栈是否为空
if(stack.isEmpty()){
stack.push(c);//将字符入栈
}else{//不为空
char top = stack.peek();//获取栈顶元素
if(top-c==-1 || top-c==-2){//判断是否匹配
stack.pop();//将栈顶出栈
}else{
stack.push(c);//将c入栈
}
}
}
return stack.isEmpty();
}
240. 搜索二维矩阵 II
编写一个高效的算法来搜索 m x n 矩阵 matrix 中的一个目标值 target。该矩阵具有以下特性:
每行的元素从左到右升序排列。
每列的元素从上到下升序排列。
示例:现有矩阵 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。
解析:我们可以根据时间的复杂度进行解题。当从每一行进行二分查找时,时间复杂度为O(mlogn);当从左上和右下开始查找时,方向无法确定;当从左下角的位置开始查询,时间复杂度为O(m+n);由此我们可以选择从左下角的位置开始查找。那什么时候找不到呢?当查到右上角的时候,如果比它小往上走,如果比它大往右走,此时我们会发现它已经走出去了,说明没有找到该元素。
public boolean searchMatrix(int[][] matrix, int target) {
//1.数组对象压根就没有
//2.对象有,没数据
//3.对象有,有行,行中无元素
if(matrix==null||matrix.length==0||matrix[0].length==0){
return false;
}
int row=matrix.length; //行
int col=matrix[0].length; //列
//左下角的位置
int x=row-1;
int y=0;
while(true){
if(x<0||y>=col){//没有找到
return false;
}
if(matrix[x][y]<target){
y++;
}else if(matrix[x][y]>target){
x--;
}else{
return true;
}
}
}
209. 长度最小的子数组
给定一个含有 n 个正整数的数组和一个正整数 s ,找出该数组中满足其和 ≥ s 的长度最小的连续子数组。如果不存在符合条件的连续子数组,返回 0。
示例:
输入: s = 7, nums = [2,3,1,2,4,3]
输出: 2
解释: 子数组 [4,3] 是该条件下的长度最小的连续子数组。
解析:根据题意,我们可以利用滑窗机制,用两个指针对数组进行动态变化。先将第一个数放入窗口,加入第二个数,然后跟目标值进行对比,如果s大的话,继续往里加数,当大于等于s时候,记录窗口中的长度,然后将前面先进的数减掉,再跟s比较,如果大于等于s的话,再减掉前的数,等到减到小于s的时候,再往里加数,重复上述操作,然后得出长度最小的连续数组。
public int minSubArrayLen(int s, int[] nums) {
//判断nums是否为空或nums中有无元素
if(nums==null || nums.length==0){
return 0;
}
int len=0;//记录长度
int sum=0;//记录和
int i=0;
for(int j=0;j<nums.length;j++){
sum+=nums[j];//往进加数字
while(sum>=s){
//当len=0时,j-i+1
//当len!=0时,len和j-i+1比较,谁小取谁
len=len==0?j-i+1:Math.min(len, j-i+1);
sum-=nums[i++];//往出减数字
}
}
return len;
}
54. 螺旋矩阵
给定一个包含 m x n 个元素的矩阵(m 行, n 列),请按照顺时针螺旋顺序,返回矩阵中的所有元素。
示例 1:
输入:
[
[ 1, 2, 3 ],
[ 4, 5, 6 ],
[ 7, 8, 9 ]
]
输出: [1,2,3,6,9,8,7,4,5]
示例 2:输入:
[
[1, 2, 3, 4],
[5, 6, 7, 8],
[9,10,11,12]
]
输出: [1,2,3,4,8,12,11,10,9,5,6,7]
解析:首先我们根据题意得出,只有向右、向下、向左、向上这个四种情况。
向右:detX=0 delY=1
向下:detX=1 delY=0
向左:detX=0 delY=-1
向上:detX=-1 delY=0
deltX={0,1,0,-1}
deltY={1,0,-1,0}
public List<Integer> spiralOrder(int[][] matrix) {
ArrayList<Integer> list = new ArrayList<Integer>();
if(matrix==null||matrix.length==0||matrix[0].length==0){
return list;
}
int x=0;
int y=0;
int R=matrix.length;
int C=matrix[0].length;
boolean[][] visited = new boolean[R][C];
int[] deltX={0,1,0,-1};
int[] deltY={1,0,-1,0};
int dir=0;
for(int i=0;i<R*C;i++){
list.add(matrix[x][y]);
visited[x][y]=true;
int nx=x+deltX[dir];
int ny=y+deltY[dir];
if(nx>=0&&nx<R&&ny>=0&&ny<C&&!visited[nx][ny]){
x=nx;
y=ny;
}else{
dir=(dir+1)%4;
x+=deltX[dir];
y+=deltY[dir];
}
}
return list;
}