数组算法精讲:从入门到实战
CSDN 小白入门详解文档:数组与常见算法题精讲
前言
很多刚接触算法题或者准备面试的同学,会觉得题目描述晦涩难懂,代码逻辑也不好记。本文将结合经典的数组题目(移除元素、合并有序数组、寻找中心下标、寻找缺失数字、奇偶排序、超过 25% 出现的元素、连续递增子序列等),逐一拆解思路,并提供详细的代码示例与讲解,帮助你在刷题中打下坚实的基础。
移除元素(Remove Element)
题目描述
给定一个数组 nums
和一个数值 val
,请你原地移除所有等于 val
的元素,并返回移除后数组的新长度。
解题思路
-
使用一个 快慢指针:
- 快指针遍历数组;
- 慢指针记录下一个应该放置的非
val
元素的位置。
-
遍历完成后,慢指针的位置就是新数组长度。
示例代码
int removeElement(int* nums, int numsSize, int val) {int k = 0; // 慢指针,记录新数组长度for (int i = 0; i < numsSize; i++) {if (nums[i] != val) {nums[k] = nums[i]; // 把非 val 元素前移k++;}}return k;
}
合并两个有序数组(Merge Sorted Array)
题目描述
给定两个升序数组 nums1
和 nums2
,将 nums2
合并到 nums1
中,使结果仍为升序。
解题思路
- 从后往前遍历,利用双指针
i
和j
指向两个数组的末尾,k
指向合并后数组的末尾。 - 比较
nums1[i]
和nums2[j]
,把较大的放到nums1[k]
,然后相应指针左移。
示例代码
void merge(int* nums1, int m, int* nums2, int n) {int i = m - 1; // nums1 有效部分末尾int j = n - 1; // nums2 末尾int k = m + n - 1; // 合并后数组末尾while (i >= 0 && j >= 0) {if (nums1[i] > nums2[j]) {nums1[k--] = nums1[i--];} else {nums1[k--] = nums2[j--];}}// 如果 nums2 还有剩余元素while (j >= 0) {nums1[k--] = nums2[j--];}
}
寻找数组的中心下标(Find Pivot Index)
题目描述
数组的中心下标是指左侧元素和等于右侧元素和的位置。
解题思路
- 先计算数组总和
total
; - 遍历数组,用
leftSum
记录左侧和; - 判断
leftSum == total - leftSum - nums[i]
是否成立。
示例代码
int pivotIndex(int* nums, int numsSize) {int total = 0, leftSum = 0;for (int i = 0; i < numsSize; i++) total += nums[i];for (int i = 0; i < numsSize; i++) {if (leftSum == total - leftSum - nums[i]) return i;leftSum += nums[i];}return -1;
}
寻找缺失的数字(Missing Number)
题目描述
给定一个包含 n
个不同数字的数组,范围是 0 ~ n
,找出缺失的那个数。
解题思路
-
数学方法:
- 总和公式:0+1+2+...+n=n(n+1)/20+1+2+...+n = n(n+1)/20+1+2+...+n=n(n+1)/2
- 遍历数组,减去已有的数,剩下的就是缺失数。
示例代码
int missingNumber(int* nums, int numsSize) {int expected = numsSize * (numsSize + 1) / 2;int actual = 0;for (int i = 0; i < numsSize; i++) actual += nums[i];return expected - actual;
}
按奇偶排序数组(Sort Array By Parity)
题目描述
给定一个数组,将所有偶数排在前面,奇数排在后面。
解题思路
- 使用双指针:
i
从左向右,j
从右向左。 - 如果
nums[i]
是奇数而nums[j]
是偶数,则交换。
示例代码
void sortArrayByParity(int* nums, int numsSize) {int i = 0, j = numsSize - 1;while (i < j) {if (nums[i] % 2 > nums[j] % 2) {int tmp = nums[i];nums[i] = nums[j];nums[j] = tmp;}if (nums[i] % 2 == 0) i++;if (nums[j] % 2 == 1) j--;}
}
超过 25% 出现的元素(Element Appearing More Than 25% in Sorted Array)
题目描述
给定一个非递减数组,找到出现次数超过 25% 的元素。
解题思路
- 由于数组有序,超过 25% 的元素必然出现在某个固定间隔(如
i, i + n/4
)之间。 - 只需检查几个候选值是否满足条件。
示例代码
int findSpecialInteger(int* arr, int arrSize) {int span = arrSize / 4;for (int i = 0; i + span < arrSize; i++) {if (arr[i] == arr[i + span]) return arr[i];}return -1;
}
最长连续递增子序列(Longest Continuous Increasing Subsequence)
题目描述
给定数组,找到最长的连续递增子序列的长度。
解题思路
- 遍历数组,用
count
记录当前递增长度; - 遇到非递增时重置为 1;
- 用
maxLen
记录最大值。
示例代码
int findLengthOfLCIS(int* nums, int numsSize) {if (numsSize == 0) return 0;int maxLen = 1, count = 1;for (int i = 1; i < numsSize; i++) {if (nums[i] > nums[i - 1]) {count++;if (count > maxLen) maxLen = count;} else {count = 1;}}return maxLen;
}
总结
本文从多个典型数组题入手,系统讲解了:
- 移除元素(快慢指针)
- 合并有序数组(双指针从后往前)
- 寻找中心下标(左右和平衡)
- 寻找缺失数字(数学公式)
- 按奇偶排序(双指针交换)
- 找到超过 25% 的元素(区间检查)
- 最长连续递增子序列(动态统计)