数组
数组是存放在连续内存空间上的相同类型数据的集合。
注意:
- 数组下标都是从0开始的。
- 数组内存空间的地址是连续的
正是因为数组的在内存空间的地址是连续的,所以我们在删除或者增添元素的时候,就难免要移动其他元素的地址。数组的元素是不能删的,只能覆盖。
//自己写的
public static int search(int[] nums, int target) {
for (int i = 0; i < nums.length; i++) {
if (nums[i] == target){
return i;
}
}
return -1;
}
//做法二:二分查找。这道题目的前提是数组为有序数组,同时题目还强调数组中无重复元素
public int search(int[] nums, int target) {
// 避免当 target 小于nums[0] nums[nums.length - 1]时多次循环运算
if (target < nums[0] || target > nums[nums.length - 1]) {
return -1;
}
//left right mid都是指数组的索引
int left = 0;
int right = nums.length - 1;
int mid = (left + right) / 2;
while (left <= right) {
//目标元素在数组的右边
if (target > nums[mid]) {
left = mid + 1;
mid = (left + right) / 2;
}
//目标元素在数组的左边
if (target < nums[mid]) {
right = mid - 1;
mid = (left + right) / 2;
}
if (target == nums[mid]) {
return mid;
}
}
return -1;
}
//暴力
public static int removeElement2(int[] nums, int val) {
int size = nums.length;
//外循环:遍历数组的
for (int i = 0; i < size; i++) {
if (nums[i] == val) {
//内循环:更新数组
for (int j = i + 1; j < size; j++) {
//将i后面的元素都往前移动一位,数组的长度--
nums[j - 1] = nums[j];
}
i--; // 因为下标i以后的数值都向前移动了一位,所以i也向前移动一位
size--;
}
}
return size;
}
public static int removeElement(int[] nums, int val) {
// 双指针:操作的是同一个数组
int slowIndex = 0; //慢指针:获取新数组的元素
int fastIndex = 0; //快指针:获取新数组中需要更新的位置
for (fastIndex = 0; fastIndex < nums.length; fastIndex++) {
//新数组中不应该有目标元素
if (nums[fastIndex] != val) {
nums[slowIndex] = nums[fastIndex];
slowIndex++;
}
}
return slowIndex;
}
//两两交换:将 非0元素 与 第一个为0元素的索引 进行交换
public static void moveZeroes2(int[] nums) {
if (nums == null) {
return;
}
int i = 0; //i 用于遍历数组中的每个元素
int j = 0; //j 用于跟踪最后一个非零元素的位置
while (i < nums.length) {
if (nums[i] != 0) {
int tmp = nums[j];
nums[j] = nums[i];
nums[i] = tmp;
j++;
}
i++;
}
}
第四题:844. 比较含退格的字符串 - 力扣(LeetCode)
public boolean backspaceCompare(String s, String t) {
StringBuilder ssb = new StringBuilder();
StringBuilder tsb = new StringBuilder();
// 分别处理两个字符串
for (char c : s.toCharArray()) {
if (c != '#') {
ssb.append(c); // 模拟进栈的操作
} else if (ssb.length() > 0) { // 栈非空才能弹出
ssb.deleteCharAt(ssb.length() - 1); // 将栈顶元素弹出
}
}
for (char c : t.toCharArray()) {
if (c != '#') {
tsb.append(c); // 模拟进栈的操作
} else if (tsb.length() > 0) { // 栈非空才能弹出
tsb.deleteCharAt(tsb.length() - 1); // 将栈顶元素弹出
}
}
return ssb.toString().equals(tsb.toString());
}
第五题:977. 有序数组的平方 - 力扣(LeetCode)
//自己写的
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];
}
//对arr进行递增排序
Arrays.sort(arr);
return arr;
}
//双指针思路:
public int[] sortedSquares(int[] nums) {
int right = nums.length - 1;
int left = 0;
int[] result = new int[nums.length];
int index = result.length - 1;
while (left <= right) {
if (nums[left] * nums[left] > nums[right] * nums[right]) {
// 正数的相对位置是不变的, 需要调整的是负数平方后的相对位置
result[index--] = nums[left] * nums[left];
++left;
} else {
result[index--] = nums[right] * nums[right];
--right;
}
}
return result;
}
第六题:209. 长度最小的子数组 - 力扣(LeetCode)
//暴力解法
public int minSubArrayLen(int target, int[] nums) {
int n = nums.length;
if (n == 0) {
return 0;
}
int ans = Integer.MAX_VALUE;
for (int i = 0; i < nums.length; i++) {
int sum = 0;
for (int j = i; j < nums.length; j++) {
sum = sum + nums[j];
if (sum >= target){
ans = Math.min(ans,j - i + 1);
break;
}
}
}
return ans == Integer.MAX_VALUE ? 0 : ans;
}
/*滑动窗口(相当于双指针)
窗口内是什么?
如何移动窗口的起始位置?
如何移动窗口的结束位置?
*/
public static int minSubArrayLen2(int s, int[] nums) {
int left = 0;
int sum = 0;
int result = Integer.MAX_VALUE;
int subLength = 0;
//循环表示:滑动窗口的终止位置
for (int right = 0; right < nums.length; right++) {
sum += nums[right];
while (sum >= s) { //窗口就要向前移动了(也就是该缩小了)
subLength = right - left + 1; // 取子序列的长度
result = Math.min(result, subLength);
sum -= nums[left++];
}
}
return result == Integer.MAX_VALUE ? 0 : result;
}