当前位置: 首页 > 知识库问答 >
问题:

杂耍算法

杜弘伟
2023-03-14

方法(一种杂耍算法)将数组划分为不同的集合,其中集合数等于n和d的GCD,并在集合内移动元素。如果GCD与上述示例数组(n=7,d=2)一样为1,则元素将仅在一个集合内移动,我们只需从temp=arr[0]开始,并将arr[I d]一直移动到arr[I],最后将temp存储在正确的位置。

以下是n=12和d=3的示例。GCD为3,且

设arr[]为{1,2,3,4,5,6,7,8,9,10,11,12}

a) 元素首先在第一组中移动–(此移动请参见下图)

排列

      arr[] after this step --> {4 2 3 7 5 6 10 8 9 1 11 12}

b) 然后是第二盘。此步骤后的arr[]--

c) 最后是第三盘。此步骤后的arr[]--

/*Function to get gcd of a and b*/
int gcd(int a,int b);

/*Function to left rotate arr[] of siz n by d*/
void leftRotate(int arr[], int d, int n)
{
  int i, j, k, temp;
  for (i = 0; i < gcd(d, n); i++)
  {
    /* move i-th values of blocks */
    temp = arr[i];
    j = i;
    while(1)
    {
      k = j + d;
      if (k >= n)
        k = k - n;
      if (k == i)
        break;
      arr[j] = arr[k];
      j = k;
    }
    arr[j] = temp;
  }
}

/*UTILITY FUNCTIONS*/
/* function to print an array */
void printArray(int arr[], int size)
{
  int i;
  for(i = 0; i < size; i++)
    printf("%d ", arr[i]);
}

/*Function to get gcd of a and b*/
int gcd(int a,int b)
{
   if(b==0)
     return a;
   else
     return gcd(b, a%b);
}

/* Driver program to test above functions */
int main()
{
   int arr[] = {1, 2, 3, 4, 5, 6, 7};
   leftRotate(arr, 2, 7);
   printArray(arr, 7);
   getchar();
   return 0;
}

时间复杂度:O(n)辅助空间:O(1)

有人能给我解释一下这个算法是如何工作的以及它的渐近复杂性吗?

共有2个答案

张丁雷
2023-03-14

杂耍算法

在此方法中,将数组划分为M个集合,其中M=GCD(n, k),然后旋转每个集合中的元素。

从数组的元素数(n)和要对数组进行的旋转数(k),得到块的GCD(n, k)数。然后在每个块中,将发生移位到块中相应的元素。

在移动所有块中的所有元素后,数组将旋转给定次数。

例如:如果我们想将下面的数组旋转2个位置。1 2 3 4 5 6

  M = GCD(6, 2) = 2;
  Initial Array : 1  2  3  4  5  6   
  First Set Moves : 5   2   1   4   3   6
  Second Set Moves : 5   6   1   2   3   4          //  The array is rotated twice.

public class Main
{

/*Fuction to get gcd of a and b*/
public static int gcd(int a, int b) 
{ 
    if (b == 0) 
        return a; 
    else
        return gcd(b, a % b); 
}

/*Function to left rotate array of by d number of rotations*/
public static void leftRotate(int arr[], int d, int n) 
{ 
    int i, j, k, temp; 
    for (i = 0; i < gcd(d, n); i++) // gcd(d,n) times the loop will iterate
    { 
        /* move i-th values of blocks */
        temp = arr[i]; 
        j = i; 
        while (true) { 
            k = j + d; 
            if (k >= n) // The element has to be shifted to its rotated position
                k = k - n; 
            if (k == i) // The element is already in its rotated position
                break; 
            arr[j] = arr[k]; 
            j = k; 
        } 
        arr[j] = temp; 
    }} 

//  Main function
public static void main(String[] args) 
{ 
    int arr[] = { 1, 2, 3, 4, 5, 6, 7 }; 
    int no_of_rotations = 2;
    int n = arr.length;
    System.out.println("Array Elements before rotating : "); 
    for(int i = 0 ; i < n ; i++)
    {
        System.out.print(arr[i]+ " "); // Printing elements before rotation
    }
    leftRotate(arr, no_of_rotations, n); 
    System.out.println("\nArray Elements after rotating : "); 
    for(int i = 0 ; i < n ; i++)
    {
        System.out.print(arr[i] + " "); // Printing elements after rotation
} } }
姚昊焱
2023-03-14

函数中的for循环:

leftRotate(int arr[], int d, int n)

将进行exatclygcd(d, n)迭代。现在让我们看看循环内部发生了什么:它需要所有满足:k%gcd(d, n)==i的单元格arr[k]并交换它们。当然有确切的:n/gcd(d, n),这就是函数在循环的一次迭代中将进行多少次交换。因此,函数的整个渐近时间复杂度将是O(gcd(d, n)*n/gcd(d, n))==O(n)。代码的其余部分对时间复杂度没有影响,并且几乎是自我解释的。

 类似资料:
  • 我最近了解了杂耍算法如何在线性时间内旋转数组 时间复杂度如何线性???

  • 我知道变戏法对左旋转有效。右旋转是否适合杂耍算法?如果是这样,那么需要修改什么才能使其正确旋转? 使用杂耍算法的左旋转 参考以下链接上的第三种方法 空leftRotate(int arr[], int d, int n){int i, j, k, temp; for(i=0; i 请帮助我它是否支持

  • 10.5.1 算法复杂度 为了回答上述问题,首先要明确如何衡量算法的好坏。以搜索问题为例,线性搜索算法 直接了当,易设计易实现,这算不算“好”?而二分搜索算法虽然设计实现稍难一些,但因 无需检查每一个数据而大大提高了搜索效率,这又算不算“好”? 在解决数学问题时,不论是证明定理还是计算表达式,只要证明过程正确、计算结果精 确,问题就可以认为成功地解决了,即正确性、精确性是评价数学解法好坏的标准。而

  • 陌陌 推荐算法工程师  一面面经 45分钟左右(秋招第一面) 刚开始面试官的电脑没有声音,换成微信,再加上我在实习,只能在餐厅面试有点吵,网也有点卡 1. 深挖项目(计算机视觉,所用的模型有什么特点等) 2. 竞赛(NLP,一些模型的基础知识,deberta与bert的区别等) 3. 机器学习基础知识:逻辑回归损失,参数更新公式,线性回归损失,参数更新公式,这里紧张多写了一个平方。。。。。面试官点

  • 我已经通过谷歌和堆栈溢出搜索,但我没有找到一个关于如何计算时间复杂度的清晰而直接的解释。 说代码像下面这样简单: 说一个像下面这样的循环: 这将只执行一次。 时间实际上被计算为而不是声明。

  • 在最近的一次测试中,我们得到了一个函数来计算未排序的ArrayList中出现了多少个double(不是原语double,而是一个项目出现了两次)。 我正确地确定了Big O复杂度为O(N^2),但由于我错误地确定了全部复杂度,因此只获得了部分学分。函数如下: 在他刚刚发布的考试解决方案中,他给出了这样的解释: 输入集合中有N个项,该方法通过一个缩减步骤反复调用自己,该步骤生成一个新索引N次,直到达