План курса / Все задачи / Алгоритмы и структуры данных
Поиск в сдвинутом массиве
средне
# решено
Дано число target и массив уникальных чисел nums, который изначально был отсортирован по возрастанию, а затем несколько раз последний элемент переместили в начало. Количество таких операций неизвестно и не является входным параметром.
Найдите индекс числа target в массиве или верните -1, если такого числа нет.
Пример 1:
Ввод: nums = [4,8,9,1,2], target = 9
Вывод: 2
Пример 2:
Ввод: nums = [1,2,3,4,5], target = 5
Вывод: 4
Ограничения:
len(nums) >= 1
public class Solution
{
// Находим смещение (offset) в массиве, который был сдвинут
public static int FindOffset(List<int> nums)
{
int left = -1, right = nums.Count - 1;
int lastVal = nums[nums.Count - 1]; // Последний элемент массива
while (right - left > 1)
{
int mid = (left + right) / 2;
// good bad
// [4 5 6 7 | 0 1 2]
// left right
if (nums[mid] > lastVal)
{
left = mid;
}
else
{
right = mid;
}
}
return right; // Возвращаем индекс начала "хорошей" части
}
// Обычный бинарный поиск, но смещаем на offset дополнительно
public static int Search(List<int> nums, int target)
{
if (nums.Count == 0)
{
return -1; // Если массив пустой, возвращаем -1
}
int offset = FindOffset(nums); // Находим смещение
int left = offset, right = nums.Count + offset;
while (right - left > 1)
{
int mid = (left + right) / 2;
int midIndex = mid % nums.Count; // Корректируем индекс для сдвинутого массива
if (nums[midIndex] <= target)
{
left = mid;
}
else
{
right = mid;
}
}
int realLeft = left % nums.Count; // Реальный индекс в исходном массиве
return nums[realLeft] == target ? realLeft : -1; // Возвращаем индекс или -1, если элемент не найден
}
}
#include <vector>
using namespace std;
int findOffset(const vector<int>& nums) {
int l = -1, r = nums.size() - 1;
int lastVal = nums.back();
while (r - l > 1) {
int m = (l + r) / 2;
// good bad
// [4 5 6 7 | 0 1 2]
// l r
if (nums[m] > lastVal) {
l = m;
} else {
r = m;
}
}
return r;
}
int search(const vector<int>& nums, int target) {
// обычный бинарный поиск, но смещаем на offset дополнительно
int offset = findOffset(nums);
int l = offset, r = nums.size() + offset;
while (r - l > 1) {
int m = (l + r) / 2;
if (nums[m % nums.size()] <= target) {
l = m;
} else {
r = m;
}
}
int realLeft = l % nums.size();
return nums[realLeft] == target ? realLeft : -1;
}
package main
func findOffset(nums []int) int {
l, r := -1, len(nums)-1
lastVal := nums[len(nums)-1]
for r-l > 1 {
m := (l + r) / 2
// good bad
// [4 5 6 7 | 0 1 2]
// l r
if nums[m] > lastVal {
l = m
} else {
r = m
}
}
return r
}
func search(nums []int, target int) int {
// обычный бинарный поиск, но смещаем на offset дополнительно
offset := findOffset(nums)
l, r := offset, len(nums)+offset
for r-l > 1 {
m := (l + r) / 2
if nums[m%len(nums)] <= target {
l = m
} else {
r = m
}
}
realLeft := l % len(nums)
if nums[realLeft] == target {
return realLeft
}
return -1
}
import java.util.*;
public class Solution {
public int findOffset(List<Integer> nums) {
int l = -1, r = nums.size() - 1;
int lastVal = nums.get(nums.size() - 1);
while (r - l > 1) {
int m = (l + r) / 2;
// good bad
// [4 5 6 7 | 0 1 2]
// l r
if (nums.get(m) > lastVal) {
l = m;
} else {
r = m;
}
}
return r;
}
public int search(List<Integer> nums, int target) {
// обычный бинарный поиск, но смещаем на offset дополнительно
int offset = findOffset(nums);
int l = offset, r = nums.size() + offset;
while (r - l > 1) {
int m = (l + r) / 2;
if (nums.get(m % nums.size()) <= target) {
l = m;
} else {
r = m;
}
}
int realLeft = l % nums.size();
return nums.get(realLeft) == target ? realLeft : -1;
}
}
from typing import *
def find_offset(nums: List[int]):
l, r = -1, len(nums) - 1
last_val = nums[-1]
while r - l > 1:
m = (l + r) // 2
# good bad
# [4 5 6 7 | 0 1 2]
# l r
if nums[m] > last_val:
l = m
else:
r = m
return r
def search(nums: List[int], target: int) -> int:
# обычный бинарный поиск, но смещаем на offset дополнительно
offset = find_offset(nums)
l, r = offset, len(nums) + offset
while r - l > 1:
m = (l + r) // 2
if nums[m % len(nums)] <= target:
l = m
else:
r = m
real_left = l % len(nums)
return real_left if nums[real_left] == target else -1
function findOffset(nums) {
let l = -1;
let r = nums.length - 1;
const lastVal = nums[nums.length - 1];
while (r - l > 1) {
const m = Math.floor((l + r) / 2);
// good bad
// [4 5 6 7 | 0 1 2]
// l r
if (nums[m] > lastVal) {
l = m;
} else {
r = m;
}
}
return r;
}
export function search(nums, target) {
// обычный бинарный поиск, но смещаем на offset дополнительно
const offset = findOffset(nums);
let l = offset;
let r = nums.length + offset;
while (r - l > 1) {
const m = Math.floor((l + r) / 2);
if (nums[m % nums.length] <= target) {
l = m;
} else {
r = m;
}
}
const realLeft = l % nums.length;
return nums[realLeft] === target ? realLeft : -1;
}
Оценка сложности
Время: O(log(n)), где n - число всех элементов в массиве nums