数组
- 数组是存放在连续内存空间上的相同类型数据的集合。
- 二维数组的地址:java里面没有指针,看不到每个元素的地址情况,输出的是经过处理后的数值。
public static void test_arr() {
int[][] arr = {{1, 2, 3}, {3, 4, 5}, {6, 7, 8}, {9,9,9}};
System.out.println(arr[0]);
System.out.println(arr[1]);
System.out.println(arr[2]);
System.out.println(arr[3]);
}
'''
输出如下:
[I@7852e922
[I@4e25154f
[I@70dea4e
[I@5c647e05
'''
- 数组的元素不能删除,只能覆盖。在对数组增删时,除了要处理待增删的元素,还需要移动待增删元素的后面的元素。
704 二分查找
链接:https://leetcode.cn/problems/binary-search/description/
关键词:有序、整型数组、无重复元素、查找、时间复杂度:O(log n)
1、二分查找需要注意的地方就是确定边界条件,也就是数组的区间,一般两种情况:
- 左闭右闭、
- 左闭右开
- (左开右开和左开右闭和上面类似)
2、代码:
//我写的
class Solution {
public int search(int[] nums, int target) {
//左闭右闭
int left=0;
int right=nums.length-1;
while(left<=right){
int middle;
middle=(left+right)/2;
if(target==nums[middle]){
return middle;
}
if(target>nums[middle]){
left=middle+1;
}else{
right=middle-1;
}
}
return -1;
}
}
//我写的
class Solution {
public int search(int[] nums, int target) {
//左闭右开:
int left=0;
int right=nums.length-1;
while(left<right){
int middle=(left+right)/2;
if(nums[middle]==target){
return middle;
}
if(nums[middle]<target){
left=middle+1;
}else if(nums[middle]>target){
right=middle;
}
}
return -1;
}
}
3、犯的错:
在算middle的时候,我用的:
int middle=(left+right)/2;
这种写法有溢出的风险, 因为int占四个字节,如果left+right的值超过了四个字节(-2147483648~2147483647),是会溢出的,结果会出错!
所以可以改成这种写法:
int mid = left + ((right - left) / 2);
最后,位运算相对来说会快一点,所以可以进一步改成这种写法:
int mid = left + ((right - left) >> 1);
这也是随想录里的方法。
27. 移除元素
链接:https://leetcode.cn/problems/remove-element/
关键词:原地修改、数组
1、代码
//暴力搜索
//先找到等于val的元素,再将这个元素右边的那些元素往左移一位,同时让数组的长度减一。
//下次搜索的时候,还是从相同的索引开始,如果用for循环,要注意
class Solution {
public int removeElement(int[] nums, int val) {
int k=nums.length;
int i=0;
while(i<k){
if(nums[i]!=val){
i++;
continue;
}else{
for(int j=i;j<k-1;j++){
nums[j]=nums[j+1];
}k--;
}
}
return k;
}
}
//双指针(快慢指针)
//用两个指针,第一个指针遍历数组,找符合要求的元素,所以while的中止条件是fast<nums.length。
//第二个指针更新数组的下标/值。
//注意第一个指针不管有没有找到符合要求的元素,都是要加1的。第二个指针只有在找到元素后,才加1.
class Solution {
public int removeElement(int[] nums, int val) {
int fast=0;
int slow=0;
while(fast<nums.length){
if(nums[fast]!=val){
nums[slow]=nums[fast];
slow++;
}
fast++;
}
return slow;
}
}
//相向指针
class Solution {
public int removeElement(int[] nums, int val) {
int left=0;
int right=nums.length-1;
while(left<=right){
while(left<=right&&nums[left]!=val){
left++;
}
while(right>=left&&nums[right]==val){
right--;
}
if(left<right){
nums[left]=nums[right];
left++;
right--;
}
}
return left;
}
}
2、问题:
暴力解法:我开始用的for循环,但是在外层循环时,没有注意到数组元素左移之后,下次外层循环仍然要从上次的索引开始,所以外层循环的i要减一;
for(int i=0;i<k;i++){//错误写法
if(nums[i]!=val){
i++;
continue;
}else{
for(int j=i;j<k-1;j++){
nums[j]=nums[j+1];
}k--;
//这里应该加一个i--;
}
}
双指针:快慢指针相对来说容易一点,相向指针写着写着我就晕了,循环条件各种混乱。。。。QAQ