和 for
循环相比,while
循环是一种更强大循环方式。当我们在使用 for
循环时,通常我们会提前知道循环的次数、以及循环的结束条件。
当场景满足以下条件时,我们通常会优先考虑使用 while
循环:
例如,我们需要找到一个数组中,最大的那个值,我们可以使用 for
循环来实现:
10function max(arr: number[]): number {20// 首先定义一个临时变量,用来存储最大值30let max = arr[0];40// 然后定义一个索引指针,从 1 开始,因为我们已经把第一个元素赋值给了 max,递增移动到数组最后一位50for (let i = 1; i < arr.length; i++) {60// 然后在索引指针移动的过程中,不断的比较当前元素和最大值,如果当前元素大于最大值,则替换70if (arr[i] > max) {80max = arr[i];90}10}11return max;12}
我们使用 while 循环来实现:
10function max(arr: number[]): number {20// 首先定义一个临时变量,用来存储最大值30let max = arr[0];40// 然后定义一个索引指针50let i = 1;60// 当满足条件时,进入循环体,否则退出循环70while (i < arr.length) {80if (arr[i] > max) {90max = arr[i];10}11// while 循环通常在循环体的最结尾,编写循环迭代的方式12i++;13}14return max;15}
可以看到,while 循环会把初始化定义在循环的外面,然后关注循环结束条件,最后在循环体的结尾编写迭代方式。
由于我们可以把循环的迭代条件放到循环体内部来实现,所以,while 循环通常可以应对更复杂的情况。
接下来,我们来看一个稍微复杂一点的案例
已知一个已经排好序的数组,从该数组中,找到两个数之和等于目标值
由于要找到两个数,所以我们可以使用双指针来解决这个问题,一个指针指向数组的第一个元素,另一个指针指向数组的最后一个元素。
双指针分别从数组的两端往中间移动,每移动一次算出两数和,直到找到两个数之和等于目标值
10// 在已排序数组中找出两数之和等于目标值20function twoSumSorted(arr, target) {30// 定义两个指针40let left = 0;50let right = arr.length - 1;6070// 定义循环结束条件80while (left < right) {90const sum = arr[left] + arr[right];10if (sum === target) {11// 找到目标值,结束函数执行12return [left, right];13}14// 定义迭代条件15if (sum < target) {16left++;17} else {18right--;19}20}21return [];22}
注意这里的迭代条件,由于数组是已经排好序的,因此两数之和的变化趋势是:
当两数之和小于目标值时,我们需要让两数之和变大,此时移动左指针 当两数之和大于目标值时,我们需要让两数之和变小,此时移动右指针
如果题目中是无序的数组,我们可以先对数组进行排序,然后再使用双指针来解决这个问题
当然,我们也可以使用 for 循环来实现:
10function twoSumSorted(arr, target) {20let left = 0;30let right = arr.length - 1;4050for (; left < right;) {60const sum = arr[left] + arr[right];70if (sum === target) {80return [left, right];90}10if (sum < target) {11left++;12} else {13right--;14}15}16return [];17}
从一组正整数数组中,找出和为 k 的连续子数组的最大长度