【数据结构刷题】消失的数字和轮转数组(下)

简介: 【数据结构刷题】消失的数字和轮转数组(下)

题型2:写一个函数,判断一个字符串是否为另外一个字符串旋转之后的字符串。


写一个函数,判断一个字符串是否为另外一个字符串旋转之后的字符串。

例如:给定s1 =AABCD和s2 = BCDAA,返回1

给定s1=abcd和s2=ACBD,返回0.

AABCD左旋一个字符得到ABCDA

AABCD左旋两个字符得到BCDAA

AABCD右旋一个字符得到DAABC


方法1:根据strcmp函数比较两者字符串的ascll码值。

具体实现思路是:

通过循环将arr1向左移动一位反复这个过程,并使用strcmp函数比较移动后的arr1arr2

是否相等,如果相等则返回1,表示可以通过左移变成arr2

如果遍历完整个arr1后仍无法得到arr2,则返回0,表示无法通过左移变成arr2

int is_left_move(char arr1[], char arr2[])
{
  int len = strlen(arr1);
  int i = 0;
  for (i = 0; i < len; i++)//要是遍历完arr1数组,也没有出现和arr2相同的字符串那就返回0
  {
    char tmp = arr1[0];
    int j = 0;
    for (j = 0; j < len-1; j++)
    {
      arr1[j] = arr1[j + 1];
    }
    arr1[len-1] = tmp;
    if (strcmp(arr1, arr2) == 0)//比较ascll码值
    {
      return 1;
    }
  }
  return 0;
}
#include<stdio.h>
int main()
{
  char arr1[20] = "abcdef";//abcdefabcdef
  char arr2[] = "cdefab";
  int ret = is_left_move(arr1, arr2);
  if (ret == 1)
  {
    printf("yes\n");
  }
  else
  {
    printf("no\n");
  }
  return 0;
}

说明:

该代码实现了一个函数is_left_move,用于判断一个字符串arr1是否能通过左移若干个字符的方式变成另一个字符串arr2

在这个例子中,"abcdef"可以通过左移两个字符的方式变成"cdefab",因此最终输出"yes"。

执行:

11486d622dd847c3a05c1e95f69cde41.png


方法2:通过strstr函数查找

关于strstr的说明:

strstr是C语言中的一个字符串查找函数,用于在一个字符串中查找另一个字符串的出现位置。

该函数的原型为:char *strstr(const char *str1, const char *str2);

其中,str1是要查找的字符串,str2是要在str1中查找的目标字符串,函数返回值是一个指向str1中第一次出现str2的指针,如果str2未出现,则返回NULL。


在查找str2时,函数会从str1的开头开始逐个比较字符,一旦发现不匹配的字符,就会重新从下一个字符开始继续匹配,直到找到第一个匹配的子串或者str1中的所有字符都被比较完为止。如果str2为空字符串,则函数返回str1本身。


代码实现:

int is_left_move(char arr1[], char arr2[])
{
  int len1 = strlen(arr1);
  int len2 = strlen(arr2);
  if (len1 != len2)
    return  0;
  strncat(arr1, arr1, len1);
    if (strstr(arr1, arr2))
      return 1;
    else
      return 0;
}
#include<stdio.h>
int main()
{
  char arr1[20] = "abcdef";
  char arr2[] = "cdefab";
  int ret = is_left_move(arr1, arr2);
  if (ret == 1)
  {
    printf("yes\n");
  }
  else
  {
    printf("no\n");
  }
  return 0;
}


简述一下此函数在这题的作用:

if (len1 != len2)

       return  0;


在arr1[]="abcdef"前提下,如果arr2[]=“cdef”那么在


if (strstr(arr1, arr2))

           return 1;

       else

           return 0;


函数中就会认为arr2是arr1的字串,直接返回1,但这样是不对的,题目的意思是说arr1能否左旋转


简述一下此函数在这题的作用:

strncat(arr1, arr1, len1);

在这个函数中,strncat(arr1, arr1, len1) 的作用是将 arr1 的内容复制一遍添加到 arr1 的末尾,从而形成一个新的字符串。这样做是为了处理环形移位的情况,即当将 arr1 的某些字符移动到末尾时,它们将出现在开头。通过将 arr1 复制一遍添加到末尾,可以将环形移位转换为普通的移位,从而简化字符串比较的逻辑。

代码执行:

6b19395f74864e419427cf194e05aa14.png


题型3:给定一个整数数组 nums,将数组中的元素向右轮转 k 个位置,其中 k 是非负数。


6b00238c93614310bfeee101482d800e.png

思路1: 实际上就是右旋字符串,跟上面第一题的左旋字符串有着异曲同工之妙。

5894e960daff46b5b8b2073d1896ddcc.png

void rotate(int* nums, int numsSize, int k){
       int i=0;
       k=k%numsSize;
     for(i=0;i<k;i++)
     {
       int j=0;
       int tmp=nums[numsSize-1];
       for(j=numsSize-1;j>0;j--)
          {
          nums[j]=nums[j-1];
          }
          nums[0]=tmp;
     }
}

这种方式属于暴力求解,要用较多的时间,但实际上放到vs2019上可以执行

力扣运行:

8f67c9ecf3de400c893ec2ee3c9f85c4.png

vs2019编译器:

#include<stdio.h>
void rotate(int* nums, int numsSize, int k) {
    int i = 0;
    k = k % numsSize;
    for (i = 0; i < k; i++)
    {
        int j = 0;
        int tmp = nums[numsSize - 1];
        for (j = numsSize - 1; j > 0; j--)
        {
            nums[j] = nums[j - 1];
        }
        nums[0] = tmp;
    }
}
int main()
{
    int nums[] = { 1, 2, 3, 4, 5, 6, 7 };
    int k = 0;
    scanf("%d", &k);
    int sz = sizeof(nums) / sizeof(nums[0]);
    rotate(nums, sz,  k);
    for (int i = 0; i < sz; i++) {
        printf("%d", nums[i]);
    }
}


代码执行:

f53f2ea06ca44acbbc90801a6cbe2c90.png

思路2:三步旋转法(搞清楚左部分和右部分)

93dc5018e40343c7a4c879c2ee7667fb.png

6c2d63cdea5549228a6ced63cde9f23d.png


代码实现:

void reverse(int*a,int left, int right)
{
    while (left < right)
    {
      int tmp = a[left];
        a[left] = a[right];
        a[right] = tmp;
        left++;
        right--;
    }
}
void rotate(int* nums, int numSize, int k)
{
    if (k > numSize)
        k %= numSize;
    reverse(nums, 0, numSize - k - 1);
    reverse(nums, numSize - k , numSize - 1);
    reverse(nums, 0, numSize  - 1);
}
int main()
{
    int nums[] = {1,2,3,4,5,6,7};
    int k = 0;
    scanf("%d", &k);
    int sz = sizeof(nums) / sizeof(nums[0]);
    rotate(nums, sz,  k);
    for (int i = 0; i < sz; i++) {
        printf("%d", nums[i]);
    }
}


思路3:空间换时间

思路:

4f3141639f85401bbeea4379b37da4b9.png

简述一下memcpy的作用:

在 C 语言中,memcpy是一个函数,用于在内存之间复制一定数量的字节。其函数原型为:

void* memcpy(void* destination, const void* source, size_t num);

其中,destination 是目标内存区域的指针,source 是源内存区域的指针,num 是要复制的字节数。

memcpy 函数的作用是将源内存区域中的 `num` 个字节复制到目标内存区域中。如果源和目标内存区域重叠,行为是未定义的。


以下是一个示例:

#include <stdio.h>
#include <string.h>
int main() {
    char source[] = "hello";
    char destination[6];
    memcpy(destination, source, 6);
    printf("%s\n", destination);
    return 0;
}


输出结果为:

b2dc05793e6e4457b2b9e2d559848108.png

在这个示例中,memcpy 函数将 source 数组中的 5 个字符复制到 destination 数组中。由于 destination 数组长度为 6,所以需要复制 6 个字节,其中最后一个字节会被设置为 NULL 字节,即字符串结束标志。最终输出结果为 hello

memcpy 函数通常用于需要将一个内存区域的数据复制到另一个内存区域的情况。例如,当你需要对一个字符串进行操作时,可以使用 memcpy 函数将其复制到一个缓冲区中进行处理,以避免改变原始字符串的值。此外,memcpy 函数还可以用于将任何类型的数据复制到内存中。

思路3代码实现:

#include<stdio.h>
void rotate(int* nums, int numSize, int k)
{
    if (k > numSize)
        k %= numSize;
    int* tmp = (int*)malloc(sizeof(int) * numSize);
    memcpy(tmp+k,nums,sizeof(int)*(numSize-k));
    memcpy(tmp,nums + numSize - k, sizeof(int) * (k));
    memcpy(nums, tmp, sizeof(int) * (numSize));
    free(tmp);
    tmp=NULL;
}
int main()
{
    int nums[] = {1,2,3,4,5,6,7};
    int k = 0;
    scanf("%d", &k);
    int sz = sizeof(nums) / sizeof(nums[0]);
    rotate(nums, sz,  k);
    for (int i = 0; i < sz; i++) {
        printf("%d", nums[i]);
    }
}


代码执行:

5ef2e1404ba842eb875dba0545c210ca.png

本章完,如有错误欢迎大佬指正。

相关文章
|
18天前
|
存储 Java 程序员
数据结构之 - 深入了解数组数据结构
数据结构之 - 深入了解数组数据结构
34 6
|
18天前
|
存储 算法 搜索推荐
探索常见数据结构:数组、链表、栈、队列、树和图
探索常见数据结构:数组、链表、栈、队列、树和图
84 64
|
11天前
|
算法 程序员 索引
数据结构与算法学习七:栈、数组模拟栈、单链表模拟栈、栈应用实例 实现 综合计算器
栈的基本概念、应用场景以及如何使用数组和单链表模拟栈,并展示了如何利用栈和中缀表达式实现一个综合计算器。
16 1
数据结构与算法学习七:栈、数组模拟栈、单链表模拟栈、栈应用实例 实现 综合计算器
|
11天前
|
存储 算法 定位技术
数据结构与算法学习二、稀疏数组与队列,数组模拟队列,模拟环形队列
这篇文章主要介绍了稀疏数组和队列的概念、应用实例以及如何使用数组模拟队列和环形队列的实现方法。
15 0
数据结构与算法学习二、稀疏数组与队列,数组模拟队列,模拟环形队列
|
1月前
|
存储 Java
java数据结构,线性表顺序存储(数组)的实现
文章介绍了Java中线性表顺序存储(数组)的实现。线性表是数据结构的一种,它使用数组来实现。文章详细描述了线性表的基本操作,如增加、查找、删除、修改元素,以及其他操作如遍历、清空、求长度等。同时,提供了完整的Java代码实现,包括MyList接口和MyLinearList实现类。通过main函数的测试代码,展示了如何使用这些方法操作线性表。
|
11天前
初步认识栈和队列
初步认识栈和队列
35 10
|
5天前
数据结构(栈与列队)
数据结构(栈与列队)
11 1
|
11天前
|
算法
数据结构与算法二:栈、前缀、中缀、后缀表达式、中缀表达式转换为后缀表达式
这篇文章讲解了栈的基本概念及其应用,并详细介绍了中缀表达式转换为后缀表达式的算法和实现步骤。
28 3
|
10天前
|
存储 JavaScript 前端开发
为什么基础数据类型存放在栈中,而引用数据类型存放在堆中?
为什么基础数据类型存放在栈中,而引用数据类型存放在堆中?
37 1
|
13天前
|
存储 安全 Java
【用Java学习数据结构系列】探索栈和队列的无尽秘密
【用Java学习数据结构系列】探索栈和队列的无尽秘密
25 2