有序数组arr可能经过一次旋转处理,也可能没有,且arr可能存在重复的数。例如,有序数组[1, 2, 3, 4, 5, 6, 7],可以旋转处理成[4, 5, 6, 7, 1, 2, 3]等。给定一个可能旋转过的有序数组arr,再给定一个数num,返回arr中是否含有num
关于旋转操作:可以简单的理解为把序列从某个位置切成两段然后交换位置
[要求]
期望复杂度为
第一行两个整数N, num。分别表示数组大小, 需要找的数。
接下来一行N个整数表示数组内的数。
若num存在于数组中,输出"Yes",否则输出"No"
7 7 4 5 6 7 1 2 3
Yes
7 998244353 4 5 6 7 1 2 3
No
#include<iostream> #include<vector> using namespace std; bool search(vector<int>& nums, int target) { int left = 0, right = nums.size() - 1; while( left <= right ) { int mid = left + ( right - left ) / 2; if( target == nums[mid] ) return true; if( target == nums[left] ) return true; if( target == nums[right] ) return true; // nums[left]、nums[mid]和nums[right]三者相等 if( nums[left] == nums[mid] && nums[mid] == nums[right] ) { left++; right--; } else if( nums[left] <= nums[mid] ) // 如果前半段有序 { if( nums[left] < target && target < nums[mid] ) right = mid - 1; else left = mid + 1; } else // 否则后半段有序 { if( nums[mid] < target && target < nums[right] ) left = mid + 1; else right = mid - 1; } } return false; } int main(){ int N, num; cin >> N >> num; vector<int> arr(N, 0); for(int i = 0; i < N; i++){ cin >> arr[i]; } if(search(arr,num)) cout << "Yes"; else cout << "No"; return 0; }
import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in); int n = sc.nextInt(), target = sc.nextInt(); int[] arr = new int[n]; for(int i = 0; i < n; i++) arr[i] = sc.nextInt(); int left = 0, right = n - 1; while(left < right) { int mid = left + (right - left) / 2; if(target == arr[mid] || target == arr[left] || target == arr[right]){ System.out.println("Yes"); // 找到目标,输出Yes return; } if(arr[mid] <= arr[right]){ // 右边有序 if(target > arr[mid] && target < arr[right]) left = mid + 1; // 且目标在这个区间当中 else right = mid - 1; }else{ if(arr[left] < target && arr[mid] > target) right = mid - 1; //目标在左边 else left = mid + 1; // 目标在右边 } } System.out.println("No"); } }
import java.util.*; public class Main { public static void main(String[] args) { // TODO Auto-generated method stub Scanner scan=new Scanner(System.in); while(scan.hasNext()) { int n=scan.nextInt(); int target=scan.nextInt(); int[]arr=new int[n]; for(int i=0;i<n;i++) { arr[i]=scan.nextInt(); } boolean flag=isInarr(arr,target); if(flag) System.out.println("Yes"); else System.out.println("No"); } } public static boolean isInarr(int[] arr, int key){ if(arr.length == 0){ return false; } int left = 0; int right = arr.length - 1; while (left < right){ int mid = left + (right - left)/2; if (arr[mid] == key){ return true; } //如果前半段有序 if (arr[mid] > arr[left]){ //判断Key是否在前半段,如果在,则继续遍历前半段;如果不在,则遍历后半段 if (arr[mid] > key){ right = mid - 1; }else { left = mid + 1; } } //如果后半段有序 if (arr[mid] < arr[right]){ //判断Key是否在后半段,如果在,则继续遍历后半段;如果不在,则遍历前半段 if (arr[mid] < key){ left = mid + 1; }else { right = mid - 1; } } } return false; } }
import java.util.Scanner; import java.util.Arrays; public class Main{ public static void main(String[] args){ Scanner sc=new Scanner(System.in); int n=sc.nextInt(); int num=sc.nextInt(); int[] arr=new int[n]; for(int i=0;i<n;i++){ arr[i]=sc.nextInt(); } Arrays.sort(arr); System.out.print(isInside(arr,n,num)?"Yes":"No"); } private static boolean isInside(int[] arr, int n, int num) { int left = 0; int right = n - 1; while (left < right) { int mid = (left + right) / 2; if (arr[mid] == num) { return true; } if (arr[mid] < arr[right]) { if (arr[mid] > num || arr[right] < num) { right = mid - 1; } else if (arr[right] == num){ return true; } else { left = mid + 1; } } else if (arr[mid] > arr[right]){ if (arr[mid] < num || arr[left] > num) { left = mid + 1; } else if (arr[left] == num) { return true; } else { right = mid - 1; } } else { right--; } } return false; } }
#include <cstdio> using namespace std; const int N = 100000; int n, k; int a[N]; int main(void) { scanf("%d%d", &n, &k); for ( int i = 0; i <n; ++i ) scanf("%d", a + i); --n; while ( n > 0 && a[n] == a[0] ) --n; if ( a[0] == a[n] ) { puts( a[0] == k ? "Yes" : "No"); return 0; } int l = 0, r = n, m; bool flag = false; while ( l < r ) { m = l + r >> 1; if ( a[m] == k ) { flag = true; break; } if ( a[m] >= a[0] ) { if ( a[l] <= k && k <= a[m] ) r = m; else l = m + 1; } else { if ( k <= a[m] ) r = m; else l = m + 1; } } puts( flag ? "Yes" : "No"); return 0; }上面的代码漏了个条件。。。
#include <cstdio> using namespace std; const int N = 100000; int n, k; int a[N]; int main(void) { scanf("%d%d", &n, &k); for ( int i = 0; i <n; ++i ) scanf("%d", a + i); --n; while ( n > 0 && a[n] == a[0] ) --n; if ( a[0] == a[n] ) { puts( a[0] == k ? "Yes" : "No"); return 0; } int l = 0, r = n, m; while ( l < r ) { m = l + r >> 1; if ( a[m] == k ) { puts("Yes"); return 0; } if ( a[m] >= a[0] ) { if ( a[l] <= k && k <= a[m] ) r = m; else l = m + 1; } else { if ( k <= a[m] || k > a[n]) r = m; else l = m + 1; } } puts( a[r] == k ? "Yes" : "No"); return 0; }