一道算法编程题

时间:2021-09-15 23:33:17
有一个升序整型数组,比如,{2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37}。
现在从该数组任意位置截断成两段,并前后调换位置。
比如,选取从a7=19开始截断,调换位置,变成了部分有序数组:{19, 23, 29, 31, 37, 2, 3, 5, 7, 11, 13, 17}。
写出一个算法,在这种部分有序的数组中查找指定的关键数。要求时间复杂度小于O(n)。

12 个解决方案

#1



public static void main(String[] args) {
List<Integer> list = new ArrayList<Integer>();
for(int i=200;i<1000;i++){
list.add(i+1);
}
for(int i=0;i<200;i++){
list.add(i+1);
}
int temp = new Random().nextInt(1000);
int i=0;
int j=list.size()-1;
System.out.println(temp);
while((j-i)>2){
int k = (j+i)/2;
if(temp==list.get(i)){
break;
}
if(temp > list.get(i)){
if(temp>list.get(k)){
if(list.get(k)>list.get(i)){
i=k;
}else{
j=k;
}
}else{
j=k;
}
}else{
if(temp < list.get(k)){
if(list.get(k)>list.get(i)){
i=k;
}else{
j=k;
}
}else{
i=k;
}
}
}
while(i<=j){
if(list.get(i)==temp){
break;
}
i++;
}
System.out.println(i);

}

#2


数学问题,表示关注

#3


如果知道数组长度就比较简单了,截断并且交换后,数组的第一个元素肯定比数组的最后一个元素要大。
将查找的元素与第一个元素比较
如果比第一个元素大,就挨个往前找;
如果比第一个元素小,则与最后一个元素比较
如果比最后一个元素小,则从最后一个元素挨个往前找;
如果比最后一个元素大,则找不到该元素;

#4


学习了,标记下。

#5



public class c extends f{
   
    public static void main(String[] args) {
int[] source = {1,2,3,4,5,6,7,8,9,10};
int size = source.length;
int tmp = new Random().nextInt(10);
if(tmp > size)
{
    System.out.println("truncate number is out size of length of array");
    return;
}
else
{
    int[] tmparr = new int[size];
    int k = 0;
    for(int i = tmp; i < size; i ++)
    {
tmparr[k++] = source[i];
    }
    for(int j = 0; j < tmp; j++)
    {
tmparr[k++] = source[j];
    }
    source = tmparr;
}
for(int i = 0;i < size; i++)
{
    System.out.print(source[i]);
}
    }
}

#6


O(N)以下O(1),不太可能吧,怎么也得河长度有关。
先把前N个翻转,然后后面那些翻转,最后全部翻转一下这个算法是O(n)。
系数也不算大,代码如下。

package lesson11_1_1;

public class Wan {
    int numbers[] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37};
    
    void Cut(int position)
    {
     Reverse(0,position - 1);
     Reverse(position, numbers.length - 1);
     Reverse(0, numbers.length - 1);
    }
    
    
    void Reverse(int start, int end)
    {
     int i = start, j = end;
     while(i < j)
     {
     int temp = numbers[i];
     numbers[i] = numbers[j];
     numbers[j] = temp;
    
     ++ i;
     -- j;
     }
    }
public static void main(String[] args) 
{
// TODO Auto-generated method stub
Wan w = new Wan();
w.Cut(7);
for(int i = 0; i < w.numbers.length; ++i)
System.out.println(w.numbers[i] + " ");

}

}


#7


不好意思啊。。。。题意理解错了。。。。。
这不是更简单直接上二分查找不就OK了。
先找到二分找到两段分界点,之后进行比较大的话在前面找,小的话在后面找复杂度是O(log n)


package lesson11_1_1;

public class Wan {
    static int numbers[] = {19, 23, 29, 31, 37, 2, 3, 5, 7, 11, 13, 17};
    
   
    
    static int BinSearch1()
    {//找分界点
     int start = 0;
     int end = numbers.length - 1;
     int middle =  0;
    
     while(numbers[start] > numbers[end])
     {
     if(end - start == 1)
     break;
    
     middle = (start + end) / 2;
    
     if(numbers[middle] > numbers[start])
     start = middle;
     else
     end = middle;
     }
    
     return start;
    }
    
    static int BinSearch2(int start, int end, int value)
    {
     if(value == numbers[start])
     return start;
     if(value == numbers[end])
     return end;
    
     int middle = (start + end) / 2;
     while(start < end)
     {
     if(numbers[middle] == value)
         break;
    
     else if(numbers[middle] > value)
     end = middle - 1;
     else
     start = middle + 1;
    
     middle = (start + end) / 2;
     }
     return middle;
    }
    
    static int Search(int value)
    {
     int cut = BinSearch1();
    
    
     if(value >= numbers[0])
     return BinSearch2(0,cut, value);
     else
     return BinSearch2(cut + 1, numbers.length - 1, value);
    
    }
public static void main(String[] args) 
{
// TODO Auto-generated method stub

System.out.println(Search(23));

}

}




#8


知道关键字在原数组的位置就好办了啊,比如是7
二分查找就行了。
先和数组的第一个数比较,大于这个数就在0,7之间二分查找
否则就在8,end之间二分查找

#9


这个很类似字符串翻转,直接用三次翻转算法,就可以!

#10


把题理解错了~

#11


看了几遍,终于看懂楼主题目的意思了。

7楼的代码是对的

#12


取数组第一个元素,比较,
如果待查元素比第一个元素大、则向后比较查找,直到数组后续元素比前一个元素小;
如果待查元素比第一个元素小、则从数组末尾向前开始查找,直到数组前序元素比当前大。

算法时间复杂度应该近似O(n)而不等O(n)吧?

#1



public static void main(String[] args) {
List<Integer> list = new ArrayList<Integer>();
for(int i=200;i<1000;i++){
list.add(i+1);
}
for(int i=0;i<200;i++){
list.add(i+1);
}
int temp = new Random().nextInt(1000);
int i=0;
int j=list.size()-1;
System.out.println(temp);
while((j-i)>2){
int k = (j+i)/2;
if(temp==list.get(i)){
break;
}
if(temp > list.get(i)){
if(temp>list.get(k)){
if(list.get(k)>list.get(i)){
i=k;
}else{
j=k;
}
}else{
j=k;
}
}else{
if(temp < list.get(k)){
if(list.get(k)>list.get(i)){
i=k;
}else{
j=k;
}
}else{
i=k;
}
}
}
while(i<=j){
if(list.get(i)==temp){
break;
}
i++;
}
System.out.println(i);

}

#2


数学问题,表示关注

#3


如果知道数组长度就比较简单了,截断并且交换后,数组的第一个元素肯定比数组的最后一个元素要大。
将查找的元素与第一个元素比较
如果比第一个元素大,就挨个往前找;
如果比第一个元素小,则与最后一个元素比较
如果比最后一个元素小,则从最后一个元素挨个往前找;
如果比最后一个元素大,则找不到该元素;

#4


学习了,标记下。

#5



public class c extends f{
   
    public static void main(String[] args) {
int[] source = {1,2,3,4,5,6,7,8,9,10};
int size = source.length;
int tmp = new Random().nextInt(10);
if(tmp > size)
{
    System.out.println("truncate number is out size of length of array");
    return;
}
else
{
    int[] tmparr = new int[size];
    int k = 0;
    for(int i = tmp; i < size; i ++)
    {
tmparr[k++] = source[i];
    }
    for(int j = 0; j < tmp; j++)
    {
tmparr[k++] = source[j];
    }
    source = tmparr;
}
for(int i = 0;i < size; i++)
{
    System.out.print(source[i]);
}
    }
}

#6


O(N)以下O(1),不太可能吧,怎么也得河长度有关。
先把前N个翻转,然后后面那些翻转,最后全部翻转一下这个算法是O(n)。
系数也不算大,代码如下。

package lesson11_1_1;

public class Wan {
    int numbers[] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37};
    
    void Cut(int position)
    {
     Reverse(0,position - 1);
     Reverse(position, numbers.length - 1);
     Reverse(0, numbers.length - 1);
    }
    
    
    void Reverse(int start, int end)
    {
     int i = start, j = end;
     while(i < j)
     {
     int temp = numbers[i];
     numbers[i] = numbers[j];
     numbers[j] = temp;
    
     ++ i;
     -- j;
     }
    }
public static void main(String[] args) 
{
// TODO Auto-generated method stub
Wan w = new Wan();
w.Cut(7);
for(int i = 0; i < w.numbers.length; ++i)
System.out.println(w.numbers[i] + " ");

}

}


#7


不好意思啊。。。。题意理解错了。。。。。
这不是更简单直接上二分查找不就OK了。
先找到二分找到两段分界点,之后进行比较大的话在前面找,小的话在后面找复杂度是O(log n)


package lesson11_1_1;

public class Wan {
    static int numbers[] = {19, 23, 29, 31, 37, 2, 3, 5, 7, 11, 13, 17};
    
   
    
    static int BinSearch1()
    {//找分界点
     int start = 0;
     int end = numbers.length - 1;
     int middle =  0;
    
     while(numbers[start] > numbers[end])
     {
     if(end - start == 1)
     break;
    
     middle = (start + end) / 2;
    
     if(numbers[middle] > numbers[start])
     start = middle;
     else
     end = middle;
     }
    
     return start;
    }
    
    static int BinSearch2(int start, int end, int value)
    {
     if(value == numbers[start])
     return start;
     if(value == numbers[end])
     return end;
    
     int middle = (start + end) / 2;
     while(start < end)
     {
     if(numbers[middle] == value)
         break;
    
     else if(numbers[middle] > value)
     end = middle - 1;
     else
     start = middle + 1;
    
     middle = (start + end) / 2;
     }
     return middle;
    }
    
    static int Search(int value)
    {
     int cut = BinSearch1();
    
    
     if(value >= numbers[0])
     return BinSearch2(0,cut, value);
     else
     return BinSearch2(cut + 1, numbers.length - 1, value);
    
    }
public static void main(String[] args) 
{
// TODO Auto-generated method stub

System.out.println(Search(23));

}

}




#8


知道关键字在原数组的位置就好办了啊,比如是7
二分查找就行了。
先和数组的第一个数比较,大于这个数就在0,7之间二分查找
否则就在8,end之间二分查找

#9


这个很类似字符串翻转,直接用三次翻转算法,就可以!

#10


把题理解错了~

#11


看了几遍,终于看懂楼主题目的意思了。

7楼的代码是对的

#12


取数组第一个元素,比较,
如果待查元素比第一个元素大、则向后比较查找,直到数组后续元素比前一个元素小;
如果待查元素比第一个元素小、则从数组末尾向前开始查找,直到数组前序元素比当前大。

算法时间复杂度应该近似O(n)而不等O(n)吧?