Java:算法 - 小米面试题:一副从1到n的牌...求输出牌堆的顺序数组

问题:

一副含有1到n的牌组成的牌堆,不知道顺序,每次从牌堆顶取一张放桌子上(从左到右平铺),再取一张放牌堆底,直到牌堆没牌,最后桌子上的牌是从1到n有序,设计程序,输入n,输出牌堆的顺序数组

思路:

该题2个数组元素集合相同,顺序不同,可以看做2个数组下标一 一对应交换。我们可以模拟长度n的输入数组按题操作,取得输出数组,然后查看2个数组中同值的下标关系,来取得输入与输出的映射关系。
最后按照映射关系还原输入数组即可。

代码思路:

  1. 按照输入n,取得顺序输出数组newDeck[1,2,3…n];
  2. 复制该数组到一个arraylist上作为input,再新建一个arraylist作为output,以便模拟抽放牌过程。
    抽牌放桌上就是 input抽一张放入output的牌组,input随即删除一张牌顶牌
    然后检查input是否还有牌,有则input牌底放一张牌顶的牌,牌顶随后删除
    循环直至output牌满n张或者input无牌(此时output放的就是newDeck为输入的输出牌组)
  3. 设输入牌组是oldDeck,长度n,准备还原;
  4. 遍历newDeck的牌,每张依次和output中的牌比较,如果发现相同的牌,取得两个下标关系(输入下标和输出下标),然后,按照关系将设为输出时的newDeck依次还原,即newDeck[输出下标]还原给oldDeck[输入下标],
  5. 完成newDeck遍历时,即每个数都被还原到oldDeck,输出oldDeck即可

java代码:

public static void restoreDeck(int n){
    /*
     *deck output as described
     */ 
    Integer[] newDeck = new Integer[n];
    for(int i=0;i<n;i++){
      newDeck[i] = i+1;
    }

    /*
     *use the output deck as an example of input to get the example of output
     */ 
    var exampleInput = new ArrayList<Integer>(Arrays.asList(newDeck));
    var exampleOutput = new ArrayList<Integer>();
    while(exampleInput.size() > 0){
      exampleOutput.add(exampleInput.get(0));
      exampleInput.remove(0);
      if(exampleInput.size() > 0){
        exampleInput.add(exampleInput.get(0));
        exampleInput.remove(0);
      }
    }

    /*
     *return the newDeck elements back to oldDeck
     */ 
    int[] oldDeck = new int[n];
    for (int i=0;i<n;i++){
      for(int j=0;j<exampleOutput.size();j++){
        if (newDeck[i]==exampleOutput.get(j)){
            oldDeck[i] = newDeck[j];
        }
      }
    }
  
    System.out.println(Arrays.toString(oldDeck));
  }

测试:

  public static void main(String[] args) {
    restoreDeck(1);
    restoreDeck(2);
    restoreDeck(3);
    restoreDeck(4);
    restoreDeck(5);
    restoreDeck(6);
  }

输出:

[1]
[1, 2]
[1, 3, 2]
[1, 3, 2, 4]
[1, 5, 2, 4, 3]
[1, 4, 2, 6, 3, 5]
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 二分搜索算法的改写如下: 1. 设定左边界left为,右边界right为n-1。 2. 当left<=right时,执行以下步骤: a. 计算中间位置mid=(left+right)/2。 b. 如果a[mid]==target,则返回mid。 c. 如果a[mid]>target,则在左半部分继续搜索,将右边界right更新为mid-1。 d. 如果a[mid]<target,则在右半部分继续搜索,将左边界left更新为mid+1。 3. 如果没有找到目标元素,返回-1。 改写后的二分搜索算法可以更快地找到目标元素,因为它利用了已排好序的数组的特性,将搜索范围缩小到一半。同时,由于算法的实现比较简单,所以它也比较容易理解和实现。 ### 回答2: 二分搜索算法,也称作二分查找算法,是一种高效的查找算法。通常情况下,它是在已排好序的数组中进行查找。从数组的中间开始进行查找,如果中间元素与目标元素相等,则返回它的位置。否则,如果目标元素比中间元素大,则在数组右半部分继续查找;如果目标元素比中间元素小,则在数组左半部分继续查找。不断重复以上过程,直到找到目标元素或查找结束。 但是,在具体实现过程中,可能会出现一些误差或者缺陷,给搜索带来一些不必要的麻烦。在此,我们提出一些改进方案,以便让二分搜索算法更加稳定可靠: 1.在代码中加入边界条件检测。对于数组越界、数组为空、目标元素不存在等情况,应该添加适当的错误处理并给出提示。 2.在实现循环过程中,应该注意索引的移动方式和范围的控制。具体来说,在更新左、右边界时,应该选择符合实际情况的操作方式。比如,如果目标元素在数组的左半部分,那么应该将右边界更新为中间元素减一的位置,而不是等于中间元素的位置。 3.在计算中间位置时,应该使用准确的数值类型,并且注意避免溢出和精度误差。 综上所述,在实现二分搜索算法时,需要考虑多种情况,并且进行适当的处理。通过以上改进方案,我们可以在保证正确性的前提下,提升搜索算法的效率和鲁棒性。 ### 回答3: 二分搜索是一种高效的搜索算法,适用于已排好序的数组。其原理是将数组分成两个部分,中间位置的元素与搜索关键字进行比较,如果相等则返回中间位置,如果中间位置的元素大于搜索关键字,则在左半部分继续搜索,否则在右半部分继续搜索,直到找到目标元素或者搜索范围为空。 改写二分搜索算法,我们可以考虑两种情况:查找第一个等于给定值的元素或者查找最后一个等于给定值的元素。对于查找第一个等于给定值的元素,代码如下: ``` int binary_search_first(int a[], int n, int value){ int low = 0, high = n - 1; while(low <= high){ int mid = low + ((high - low) >> 1); if(a[mid] >= value) high = mid - 1; else low = mid + 1; } if(low < n && a[low] == value) return low; return -1; } ``` 代码中,我们使用了一个额外的判断来检查是否找到了目标元素,如果找到返回目标元素的位置,否则返回-1。 对于查找最后一个等于给定值的元素,代码如下: ``` int binary_search_last(int a[], int n, int value){ int low = 0, high = n - 1; while(low <= high){ int mid = low + ((high - low) >> 1); if(a[mid] <= value) low = mid + 1; else high = mid - 1; } if(high >= 0 && a[high] == value) return high; return -1; } ``` 代码中,我们将中间元素与目标元素进行比较,如果中间元素小于等于目标元素,则在右半部分继续搜索,否则在左半部分继续搜索。同样地,我们也使用了一个额外的判断来检查是否找到了目标元素,如果找到返回目标元素的位置,否则返回-1。 通过改写二分搜索算法,我们可以快速地在已排好序的数组中查找第一个等于或最后一个等于给定值的元素。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值