循环数组-找出最小值

本文记录了一道面试题,涉及一个循环数组,数组中的元素按升序排列,但经过某种操作后,需要找出最小值。通过二分查找的方法,分别解决了不考虑相等元素和考虑相等元素两种情况,给出了相应的代码实现。

今天面试遇到一个有意思的题,记录一下如下。

题目一:
一个循环数组,数组中原始值按升序排列(假设所有值不相等),但是现在从某个位置截断,该位置后面的元素移动到数组的最前面,找出这样的数组的最小值。如 arr = { 1,2,3,4,5,6},移动后arr = {4,5,6,1,2,3},其中最小值为1.

思路比较简单:基于二分查找
要注意的是数组为升序和降序的特殊情形。
代码如下:

public class Main {
    public static void main(String args[]) {
        int[] arr = new int[]{4, 5, 6, 1, 2, 3};
        int[] arr1 = new int[]{1, 2, 3, 4, 5, 6};
        int[] arr2 = new int[]{6, 5, 4, 3, 2, 1};
        System.out.println(findMin(arr));
        System.out.println(findMin(arr1));
        System.out.println(findMin(arr2));
    }

    public static int findMin(int[] arr) {
        int mid = 0, start = 0, end = arr.length - 1;
        while (start < end) {
            mid = (start + end) >> 1;
            if (arr[mid] > arr[end])//arr[mid]在在arr的前半部
                //这里不能使用if(arr[mid] > arr[start]),因为可能存在1,2,3,4,5,6这种情况
                start = mid + 1;
            else {//arr[mid]在在arr的后半部
                end = mid;
            }
        }
        return arr[end];
    }
}

输出如下:

1
1
1

题目二:
如果题一中数组arr中可能存在相等的元素,同样求数组中的最小值。比如 int[] arr = new int[]{5, 3, 5, 7, 5, 5},其中最小值为3.

思路:显示题目一的做法在这里不适用,因为没有考虑元素相等的情况。那么在题一思路上进行改进:
首先,也是基于二分查找;
if arr[mid] > arr[end],arr[mid]位于arr的前半部分,
else if arr[mid] < arr[end],arr[mid]位于arr的后半部分,
else if arr[mid] == arr[end],情况稍微复杂一些。
在arr[mid] == arr[end]的基础上,
if arr[mid] > arr[start], 那么arr[mid]一定位于前半部分,
else if arr[mid] < arr[start], 那么arr[mid]一定位于后半部分,
else if arr[mid] == arr[start], 那么最小值有可能在start~mid之间,也可能在mid~end之间,此时 start++, end–

代码如下:

public class Main {
    public static void main(String args[]) {
        int[] arr = new int[]{4, 5, 6, 1, 2, 3};//1
        int[] arr1 = new int[]{1, 2, 3, 4, 5, 6};//1
        int[] arr2 = new int[]{6, 5, 4, 3, 2, 1};//1
        int[] arr3 = new int[]{5, 5, 5, 6, 7, 5};//5
        int[] arr4 = new int[]{5, 3, 5, 7, 5, 5};//3
        int[] arr5 = new int[]{5, 6, 7, 5, 3, 5};//3

        System.out.println(findMinBest(arr));
        System.out.println(findMinBest(arr1));
        System.out.println(findMinBest(arr2));
        System.out.println(findMinBest(arr3));
        System.out.println(findMinBest(arr4));
        System.out.println(findMinBest(arr5));
    }

    public static int findMinBest(int[] arr) {
        int mid = 0, start = 0, end = arr.length - 1;
        while (start < end) {
            mid = (start + end) >> 1;
            if (arr[mid] > arr[end])//arr[mid]一定位于前半部
                start = mid + 1;
            else if (arr[mid] == arr[end]) {
                if (arr[mid] == arr[start]) {
                    start++;
                    end--;
                } else if (arr[mid] > arr[start])
                    end = mid - 1;
                else {//arr[mid] < arr[start]
                    end = mid;
                    start++;
                }
            } else {//arr[mid] < arr[end]
                end = mid;
            }
        }
        return arr[end];
    }
}

输出如下:

1
1
1
5
3
3
### 使用 `for` 循环查找列表中的最大值和最小值 为了在Python中使用`for`循环来查找列表的最大值和最小值,可以初始化两个变量分别存储当前遇到的最大值和最小值。随着遍历列表更新这两个变量。 ```python def find_max_min_with_for_loop(scores): if not scores: # 如果列表为空,则抛出异常 raise ValueError("The list cannot be empty.") max_score = min_score = scores[0] # 初始化最大值和最小值为第一个元素 for score in scores: if score > max_score: max_score = score # 更新最大值 elif score < min_score: min_score = score # 更新最小值 return max_score, min_score ``` 此方法确保即使列表中有负数也能正常工作,并且不需要额外的空间复杂度[^1]。 对于统计参与评分的人数,在收集分数的同时可以通过计数器完成: ```python scores = [] count = 0 while True: try: user_input = input("请输入分数或按 'q' 结束输入:") if user_input.lower() == 'q': break score = float(user_input) scores.append(score) count += 1 except ValueError: print("无效输入,请重新尝试") if scores: average = sum(scores) / len(scores) print(f"总共有 {count} 个人提交了分数") print(f"最高分是 {find_max_min_with_for_loop(scores)[0]} 和最低分是 {find_max_min_with_for_loop(scores)[1]}") ``` 这段代码实现了用户持续输入分数的功能,直到用户决定停止(`q`)为止;同时也展示了如何利用之前定义的`find_max_min_with_for_loop()`函数来获得最大值和最小值[^4]。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值