一、理论基础
一维数组
数组是存放在连续内存空间上的相同类型数据的集合。
需要两点注意的是
- 数组下标都是从0开始的。
- 数组内存空间的地址是连续的
正是因为数组的在内存空间的地址是连续的,所以我们在删除或者增添元素的时候,就难免要移动其他元素的地址。
数组的元素是不能删的,只能覆盖。
二维数组
那么二维数组在内存的空间地址是连续的么?
像Java是没有指针的,同时也不对程序员暴露其元素的地址,寻址操作完全交给虚拟机。
所以看不到每个元素的地址情况,这里我以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
这里的数值也是16进制,这不是真正的地址,而是经过处理过后的数值了,我们也可以看出,二维数组的每一行头结点的地址是没有规则的,更谈不上连续。
所以Java的二维数组可能是如下排列的方式:
二、面试考点
三、LeetCode题序
704. (简单)二分查找
给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。
- 元素是不重复的
n 将在 [1, 10000] 之间。nums 的每个元素都将在 [-9999, 9999] 之间。
class Solution {
public int search(int[] nums, int target) {
if(nums[0]>target || nums[nums.length-1]<target) {
return -1;
}
int i=0;
int j=nums.length-1;
int mid=j/2;
while(i<=j){
if(nums[mid]==target){
return mid;
}
if(nums[mid]>target){
j=mid-1;
}
if(nums[mid]<target){
i=mid+1;
}
mid=(i+j)>>1;
}
return -1;
}
}
27. (简单)移除元素
给你一个数组 nums 和一个值 val ,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。
class Solution {
public int removeElement(int[] nums, int val) {
int num=0;
for(int i=0;i<nums.length;i++){
if(nums[i]==val){
num++;
continue;
}
if(num!=0){
nums[i-num]=nums[i];
}
}
return nums.length-num;
}
}
977.(简单)有序数组的平方
给你一个按 非递减顺序 排序的整数数组 nums ,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。
class Solution {
public int[] sortedSquares(int[] nums) {
int arr[]=new int[nums.length];
int font=0;
for(int i=0;i<nums.length;i++){
if(nums[nums.length-1-i+font]*nums[nums.length-1-i+font]<nums[font]*nums[font]){
arr[nums.length-1-i]=nums[font]*nums[font];
font++;
}else{
arr[nums.length-1-i]=nums[nums.length-1-i+font]*nums[nums.length-1-i+font];
}
}
return arr;
}
}
209.(中等)长度最小的子数组
给定一个含有 n 个正整数的数组和一个正整数 target 。找出元素和>=target的子数组中长度最小的,返回最小长度。没有符合的子数组则返回0。
class Solution {
public int minSubArrayLen(int target, int[] nums) {
int i=0;
int sum=0;
int result=Integer.MAX_VALUE;
for(int j=0;j<nums.length;j++){
sum+=nums[j];
while(sum>=target){
if(result==Integer.MAX_VALUE || (j-i+1)<result) result=j-i+1;
sum-=nums[i++];
}
}
return result==Integer.MAX_VALUE?0:result;
}
}
59.(中等)螺旋矩阵II
给你一个正整数 n ,生成一个包含 1 到 n方 所有元素,且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix 。
class Solution {
public int[][] generateMatrix(int n) {
int[][] result=new int[n][n];
int start=0;
int num=n/2;
int count=1;
while(start++<=num){
for(int i=start-1;i<n-start;i++){
result[start-1][i]=count++;
}
for(int i=start-1;i<n-start;i++){
result[i][n-start]=count++;
}
for(int i=n-start;i>start-1;i--){
result[n-start][i]=count++;
}
for(int i=n-start;i>start-1;i--){
result[i][start-1]=count++;
}
}
if(n%2==1){
result[n/2][n/2]=count++;
}
return result;
}
}
76. (困难)最小覆盖子串
给你一个字符串 s 、一个字符串 t 。返回 s 中涵盖 t 所有字符的最小子串。如果 s 中不存在涵盖 t 所有字符的子串,则返回空字符串 "" 。
- t中存在重复字符
- 如果s存在这样的子串,我们保证它是唯一答案
class Solution {
public String minWindow(String s, String t) {
int i=0,j=0;
char[] arrS = s.toCharArray();
char[] arrT = t.toCharArray();
int[] arrSCount=new int[128];
int[] arrTCount=new int[128];
for (char arr : arrT) {
arrTCount[arr]++;
}
int buf=0;
int length=Integer.MAX_VALUE;
String result="";
while(j<s.length()){
if(arrTCount[arrS[j]]==0){
j++;
continue;
}
arrSCount[arrS[j]]++;
if (arrSCount[arrS[j]]<=arrTCount[arrS[j]]) buf++;
if (buf==t.length()){
while (i<s.length()){
if(arrTCount[arrS[i]]==0){
i++;
continue;
}
if (length==Integer.MAX_VALUE || length>j-i+1) {
result=s.substring(i,j+1);
length=j-i+1;
}
arrSCount[arrS[i]]--;
if (arrSCount[arrS[i]]<arrTCount[arrS[i]]){
i++;
buf--;
break;
}
i++;
}
}
j++;
}
if(length==Integer.MAX_VALUE) return "";
return result;
}
}
|