Follow up for “Find Minimum in Rotated Sorted Array”:
What if duplicates are allowed?
Would this affect the run-time complexity? How and why?
Suppose a sorted array is rotated at some pivot unknown to you beforehand.
(i.e., 0 1 2 4 5 6 7 might become 4 5 6 7 0 1 2).
Find the minimum element.
The array may contain duplicates.

难度: Hard

就是说一个从小到大排序好的数组循环移位不知多少次,求最小值。数组可以有重复值!
这就比无重复的难一些了。
可以重复会带来不少问题,之前的不重复循环移位的判定条件都要重新思考是否有效。
比如全部是1的数列,和除了某位置有个2,其余全部是1的数列,都是合法的。
上个题目中的移动和终止条件似乎都无效了

相比上题而言,这里有几个针对重复值的关键:

  • 如果左游标遇到重复值,则移动到该重复值序列的最右边(moveRight)

  • 如果右游标遇到重复值,则移动到该重复值序列的最左边(moveLeft)

还有一个边界情况:如果碰到全1的序列呢?moveLeft会一直进行下去死循环了。所以对于这种情况我们如果循环一圈发现还没有停止moveLeft的意思,就要break掉并且在返回值中进行标记了。

这个算法的时间复杂度相对于上个算法有什么变化呢?平均时间复杂度还是O(log n),但是出现了最坏的情况,全部重复或者很多重复的情况。最坏肯定是O(n)啦。上一个算法似乎不会出现这种情况吧。

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Random;
import java.util.Set;
import java.util.TreeSet;
public class ShiftFinder2 {public static int findMin(int[] array) {if (array.length == 0) {return 0;}if (array.length == 1) {return array[0];}int len = array.length;int l = 0;int r = len - 1;int cur = (l + r) / 2;while (true) {cur = moveLeft(array, cur);if (cur == -1) {cur = 0;break;}l = moveRight(array, l);r = moveLeft(array, r);if (array[cur] < array[index(cur - 1, len)]) {break;}if (l == r) {cur = l;break;}if (r == (l + 1)) {if (array[l] < array[r]) {cur = l;} else {cur = r;}break;}if (array[cur] < array[l]) {r = cur;cur = (l + r) / 2;continue;}if (array[cur] > array[r]) {l = moveRight(array, cur);cur = (l + r) / 2;continue;}r = cur;cur = (l + r) / 2;}return array[cur];}public static int moveLeft(int[] array, int pos) {int counter = 0;int len = array.length;pos = index(pos, len);while (true) {if (array[pos] != array[index(pos - 1, len)]) {return pos;}if (counter >= len) {// special casereturn -1;}pos = index(pos - 1, len);counter++;}}public static int moveRight(int[] array, int pos) {int len = array.length;pos = index(pos, len);while (true) {if (array[pos] != array[index(pos + 1, len)]) {return pos;}pos = index(pos + 1, len);}}public static int index(int cur, int length) {return (cur % length + length) % length;}public static void main(String[] args) {int[] a = { 7, 8, 11, 12, 13, 14, 19, 22, 1, 2, 4, 5 };int[] b = { 1, 2, 3, 4, 5, 6, 7 };int[] c = { 11, 1, 2, 4, 5, 7, 8 };int[] d = { 1 };int[] e = { 1, 2 };int[] f = { 2, 1 };int[] g = { 3, 1, 2 };int[] h = { 1, 1, 1, 1, 1, 1 };int[] m = { 2, 1, 1, 1, 1, 1, 1 };int[] n = { 2, 2, 1, 1, 1, 1, 1, 1, 2 };int[] o = { 1, 1, 1, 1, 1, 1, 1, 2 };int[] p = { 1, 1, 1, 1, 1, 1, 2, 2 };int[] q = { 5, 5, 1, 3, 3, 3, 3, 3, 3, 4 };int[] r = { 4, 4, 5, 6, 6, 6, 6, 7, 9, 1, 1, 2 };int[] s = { 18, 18, 18, 19, 19, 19, 20, 20, 20, 20, 20, 20, 21, 21, 21, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23,24, 24, 25, 25, 25, 25, 26, 27, 27, 27, 27, 28, 28, 29, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 5, 6,6, 7, 8, 8, 9, 9, 9, 9, 10, 10, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 13, 13, 13, 13, 14, 14, 14,14, 15, 15, 16, 17, 17, 17, 17, 17, 17, 18, 18 };int[] t = { 7, 7, 8, 8, 8, 9, 9, 9, 9, 9, 10, 10, 10, 11, 11, 12, 12, 12, 12, 12, 13, 14, 14, 15, 15, 15, 15,16, 16, 17, 17, 17, 17, 18, 18, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22,23, 23, 23, 23, 24, 24, 25, 26, 28, 28, 28, 28, 29, 29, 29, 29, 0, 0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 3,3, 3, 3, 4, 4, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7 };int[] u = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1 };int[] v = { 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 };System.out.println(ShiftFinder2.findMin(a));System.out.println(ShiftFinder2.findMin(b));System.out.println(ShiftFinder2.findMin(c));System.out.println(ShiftFinder2.findMin(d));System.out.println(ShiftFinder2.findMin(e));System.out.println(ShiftFinder2.findMin(f));System.out.println(ShiftFinder2.findMin(g));System.out.println(ShiftFinder2.findMin(h));System.out.println(ShiftFinder2.findMin(m));System.out.println(ShiftFinder2.findMin(n));System.out.println(ShiftFinder2.findMin(o));System.out.println(ShiftFinder2.findMin(p));System.out.println(ShiftFinder2.findMin(q));System.out.println(ShiftFinder2.findMin(r));System.out.println(ShiftFinder2.findMin(s));System.out.println(ShiftFinder2.findMin(t));System.out.println(ShiftFinder2.findMin(u));System.out.println(ShiftFinder2.findMin(v));// gen non-repeatable random shift arraySystem.out.println("----- test non-repeatable shift array -----");int attemptSize = 100;int randomRange = 999;Random rdm = new Random();Set<Integer> ts = new TreeSet<Integer>();for (int i = 0; i < attemptSize; i++) {ts.add(rdm.nextInt(randomRange));}int shift = rdm.nextInt(ts.size());System.out.println("size: " + ts.size() + "; shift: " + shift);Integer[] iay = new Integer[ts.size()];ts.toArray(iay);int[] aa = new int[ts.size()];for (int i = 0; i < ts.size(); i++) {aa[ShiftFinder2.index(i + shift, aa.length)] = iay[i];}for (int i = 0; i < aa.length; i++) {System.out.print(aa[i] + " ");}System.out.println();System.out.println("non-repeatable random minimum find: " + ShiftFinder2.findMin(aa));System.out.println();// gen repeatable random shift arraySystem.out.println("----- test repeatable shift array -----");attemptSize = 100;randomRange = 30;shift = rdm.nextInt(attemptSize);System.out.println("size: " + attemptSize + "; shift: " + shift);List<Integer> jay = new ArrayList<Integer>();for (int i = 0; i < attemptSize; i++) {jay.add(rdm.nextInt(randomRange));}Collections.sort(jay);int[] bb = new int[attemptSize];for (int i = 0; i < attemptSize; i++) {bb[ShiftFinder2.index(i + shift, attemptSize)] = jay.get(i);}for (int i = 0; i < attemptSize; i++) {System.out.print(bb[i] + " ");}System.out.println();System.out.println("repeatable random minimum find: " + ShiftFinder2.findMin(bb));System.out.println();}
}

在这里,测试用例也进行了增加,尽量覆盖各种奇葩情况。后面除了不重复的随机移位数列之外,还有可重复的随机移位序列。

提交的代码:

public class Solution {public int findMin(int[] array) {if (array.length == 0) {return 0;}if (array.length == 1) {return array[0];}int len = array.length;int l = 0;int r = len - 1;int cur = (l + r) / 2;while (true) {cur = moveLeft(array, cur);if (cur == -1) {cur = 0;break;}l = moveRight(array, l);r = moveLeft(array, r);if (array[cur] < array[(cur+len-1)%len]) {break;}if (l == r) {cur = l;break;}if (r == (l + 1)) {if (array[l] < array[r]) {cur = l;} else {cur = r;}break;}if (array[cur] < array[l]) {r = cur;cur = (l + r) / 2;continue;}if (array[cur] > array[r]) {l = moveRight(array, cur);cur = (l + r) / 2;continue;}r = cur;cur = (l + r) / 2;}return array[cur];        }public static int moveLeft(int[] array, int pos) {int counter = 0;int len = array.length;while (true) {if (array[pos] != array[(pos+len-1)%len]) {return pos;}if (counter >= len) {// special casereturn -1;}pos = (pos+len-1)%len;counter++;}}public static int moveRight(int[] array, int pos) {int len = array.length;while (true) {if (array[pos] != array[(pos+1)%len]) {return pos;}pos = (pos+1)%len;}}
}

LeetCode 154 在有序旋转数组中找最小-2相关推荐

  1. html5数组查找第二大数,2021-06-29:在两个都有序的数组中找整体第K小的数。

    2021-06-29:在两个都有序的数组中找整体第K小的数. 福大大 答案2021-06-29: 1.A和B长度不等的时候,需要把A和B的长度变成相等. A是短数组,B是长数组. 第k小的数,k从1开 ...

  2. 在两个有序的数组中找第N个数,二分查找 O(lgm+lgn)级

    在两个有序的数组中找第N个数,O(lgm+lgn)级 分类: 算法2009-10-09 20:52 981人阅读 评论(3) 收藏 举报 问题描述: Give a divide and conquer ...

  3. 数据结构与算法--查找与排序另类用法-旋转数组中的最小数字

    查找与排序 查找 查找与排序都在程序设计中常被用到的算法.查找相对而言简单,一般都是顺序查找,二分查找,哈希表查找,和二叉排序树查找.其中二分查找是我必须熟悉的一种. 哈希表和二叉排序树主要点在于他的 ...

  4. 剑指Offer面试题:6.旋转数组中的最小数字

    一 题目:旋转数组中的最小数字 题目:把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转.输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素.例如数组{3,4,5,1,2}为{1, ...

  5. 在有序旋转数组中找到最小值

    题目 有序数组arr可能经过一次旋转处理,也可能没有,且arr可能存在重复的数.例如,有序数组[1,2,3,4,5,6,7],可以旋转处理成[4,5,6,7,1,2,3]等.给定一个可能旋转过的有序数 ...

  6. 输出一个为递增排序数组的旋转数组中的最小元素——8

    把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转.输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素.例如数组{3,4,5,1,2}为数组{1, 2,3, 4, 5}的一个旋转, ...

  7. 旋转数组中的最小元素 java_程序员算法面试题之旋转数组的最小值

    本文参考书籍 <剑指offer> 作者何海涛 01 题目:数组最小值 把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转. 输入一个递增排序的数组,输出旋转数组的最小元素.例 ...

  8. 剑指Offer之旋转数组中的最小数字(题8)

    1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 3 ...

  9. 数据结构与算法--有序数组中找出和为s的两个数字

    有序数组中找和为s的两个数字 题目:输入一个递增排序的数组array, 和一个数字s, 在数组中找出两个数,使得这两个数的和是s,如果有多对,输出一对即可. 最简单方案 双循环,每次获取一个数据,和数 ...

最新文章

  1. MySQL 5.7中的更多改进,包括计算列
  2. 一个程序看fputc和fgetc
  3. SharePoint 2013 Workflow 状态栏失效
  4. centos磁盘空间满查询和移动命令小记
  5. 后台原理_从浏览器如何进入路由器后台【详细介绍】
  6. hive ALLOW_UNQUOTED_CONTROL_CHARS
  7. UIDevice通知,键盘通知
  8. koa cookie使用
  9. ios html 调试,使用iframe和vconsole调试ios网页
  10. 解决org.apache.ibatis.binding.BindingException: Invalid bound statement (not found)错误
  11. 从源码角度分析Android系统的异常捕获机制是如何运行的
  12. CCF大专委2019年大数据发展趋势预测
  13. logistics回归分析+代码详解
  14. 安装出现 PHP Extension curl must be loaded 错误(magento)
  15. 02. 最好使用C++转型操作符
  16. 导入web项目运行报错找不到包
  17. 桂林老兵php,中间件解析漏洞
  18. creo外观库_Proe/Creo外观着色与贴图
  19. js日期格式化 YYMMDD 转 YY-MM-DD 转 YY年MM月DD日
  20. 小米2s刷原生安卓_小米2/2s/2a刷android4.4教程(附2/2s/2a安卓4.4卡刷包下载)

热门文章

  1. golang依赖接口,不要依赖具体实现
  2. 获取当前登录的QQ号码
  3. zookeeper专题:使用zookeeper客户端实现动态监听节点并获取数据
  4. java test 用法,pytest基本用法简介
  5. 外星人bios按f2调风扇_外星人电脑上海维修站地址「上海市飞雕国际大厦2703室」...
  6. Oracle用rowid删除同一张表的重复记录
  7. 如何扩展Laravel Auth来满足项目需求
  8. html高度的属性的值,html – 行高属性是否可以继承父Div的高度属性或其所属Div的访问高度属性?...
  9. Jackson使用详解
  10. sprinboot整合activity