数组是存放在连续内存空间上的相同类型数据的集合。
数组下标都是从0开始的,内存空间的地址是连续的。因而在删除或者增添元素的时候,难免会移动其他元素的地址。数组的元素是不能删的,只能覆盖。
题目:给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。
题目分析:有序数组;数组中无重复元素。(很适合二分查找
class Solution {
public int search(int[] nums, int target) {
int left = 0, right = nums.length - 1;
while(left <= right){ //注意这是<=
int mid = (left + right) / 2;
if(nums[mid] < target){
left = mid + 1;
}else if(nums[mid] == target){
return mid;
}else{
right = mid - 1;
}
}
return -1;
}
}
题目:给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。不要使用额外的数组空间,你必须仅使用 O ( 1 ) O(1) O(1) 额外空间并原地修改输入数组。元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。
题目分析:数组元素只能覆盖。不能进行移除。可以使用快慢指针在一个for循环完成两个for循环的事情。
class Solution {
public int removeElement(int[] nums, int val) {
//快慢指针
int fast = 0;
int slow;
for(slow = 0; fast < nums.length; fast++){
if(nums[fast] != val){
nums[slow++] = nums[fast];
}
}
return slow;
}
}
题目:给你一个按 非递减顺序 排序的整数数组 nums,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。
题目分析:
暴力解决:直接值进行平方,然后再排序。
class Solution {
public int[] sortedSquares(int[] nums) {
int[] arr = new int[nums.length];
for (int i = 0; i < nums.length; i++) {
arr[i] = nums[i] * nums[i];
}
Arrays.sort(arr);
return arr;
}
}
快慢指针:因为数组一开始是有序的,那么平方后最大的值只能是在两端,就可以双指针,一个指向起始位置,一个指向最后位置,向中间不断靠近直到相遇。
class Solution {
public int[] sortedSquares(int[] nums) {
int n = nums.length;
int[] arr = new int[n];
int left = 0, right = n - 1;
int index = n - 1;
while(left <= right){
if(nums[left] * nums[left] < nums[right] * nums[right]){
arr[index--] = nums[right] * nums[right];
right--;
}else{
arr[index--] = nums[left] * nums[left];
left++;
}
}
return arr;
}
}
题目:给定一个含有 n 个正整数的数组和一个正整数 s ,找出该数组中满足其和 ≥ s 的长度最小的 连续 子数组,并返回其长度。如果不存在符合条件的子数组,返回 0。
题目分析:用滑动窗口解决问题。滑动窗口就是调节子序列的起始和最终位置来找到结果。滑动窗口的绝妙之处在于根据当前子序列和大小的情况,不断调节子序列的起始位置。
class Solution {
public int minSubArrayLen(int target, int[] nums) {
int left = 0; //滑动窗口的起始位置
int sum = 0; //滑动窗口数值之和
int result = Integer.MAX_VALUE;
for(int right = 0; right < nums.length; right++){
sum += nums[right];
//每次更新left(起始位置),并不断比较子序列是否符合条件
while(sum >= target){
//取得子序列的长度
result = Math.min(result, right - left + 1);
//在符合条件下,把窗口缩小看还能不能符合条件,直到找到最小长度
sum -= nums[left++];
}
}
//如果result没有被赋值的话就表明没有符合条件的子序列,返回0
return result == Integer.MAX_VALUE ? 0 : result;
}
}
题目:给定一个正整数 n,生成一个包含 1 到 n 2 n^2 n2 所有元素,且元素按顺时针顺序螺旋排列的正方形矩阵。
示例:输入: 3 输出: [ [ 1, 2, 3 ], [ 8, 9, 4 ], [ 7, 6, 5 ] ]
题目分析:循环不变量原则。
模拟顺时针画矩阵的过程:
画四条边,每一条边都要坚持一致的左闭右开(或者左开右闭)原则,一圈下来都按照统一的规则画下去,拐角处让新的一条边来继续画。
易错点:
i—>X j—>Y
上下侧是看有好多列 故用j
左右侧是看有好多行 故用i
X Y是i j的起始位置 故下侧和左侧是j > Y i > X
class Solution {
public int[][] generateMatrix(int n) {
int[][] res = new int[n][n];
//循环次数
int loop = n / 2;
//定义每次循环起始位置
int startX = 0, startY = 0;
//定义偏移量
int offset = 1;
//定义填充数字
int count = 1;
//定义中间位置
int mid = n / 2;
while(loop > 0){
//i对应X,j对应Y(相当于X横轴,Y纵轴
int i = startX;
int j = startY;
//每一次循环要少前后两个元素 因而offset在后面是+2 X、Y表示i,j下标开始的位置 因为每次只输出一个元素 因而X、Y每次只+1
//模拟上侧从左到右
for(; j < startY + n - offset; ++j){
res[startX][j] = count++;
}
//模拟右侧从上到下
for(; i < startX + n - offset; ++i){
res[i][j] = count++;
}
//模拟下侧从右到左
for(; j > startY; j--){
res[i][j] = count++;
}
//模拟左侧从下到上
for(; i > startX; i--){
res[i][j] = count++;
}
loop--;
startX += 1;
startY += 1;
offset += 2;
}
if(n % 2 == 1){
res[mid][mid] = count;
}
return res;
}
}