ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

C语言错题集

2021-07-25 17:00:36  阅读:313  来源: 互联网

标签:ListNode struct int 样例 next 链表 错题 C语言


C语言错题集

PTA 练习2-6 计算物体自由下落的距离 (5 分)

一个物体从100米的高空自由落下。编写程序,求它在前3秒内下落的垂直距离。设重力加速度为10米/秒2。

输入格式:

本题目没有输入。

输出格式:

按照下列格式输出

height = 垂直距离值

结果保留2位小数。

#include<stdio.h>
int main(){
    float height,i,j;//看题!2位小数!
    height = 0.5*10*9;
    printf("height = %.2f",height);//看题!2位小数!
}

练习2-12 输出华氏-摄氏温度转换表 (15 分)

输入2个正整数lowerupperlowerupper≤100),请输出一张取值范围为[lowerupper]、且每次增加2华氏度的华氏-摄氏温度转换表。
温度转换的计算公式:C=5×(F−32)/9,其中:C表示摄氏温度,F表示华氏温度。

输入格式:

在一行中输入2个整数,分别表示lowerupper的值,中间用空格分开。

输出格式:

第一行输出:“fahr celsius”
接着每行输出一个华氏温度fahr(整型)与一个摄氏温度celsius(占据6个字符宽度,靠右对齐,保留1位小数)。//指的是celsius
若输入的范围不合法,则输出"Invalid."。

输入样例1:

 32 35

输出样例1:

fahr celsius
32   0.0
34   1.1

输入样例2:

40 30

输出样例2:

Invalid.

#include<stdio.h>
int main(){
    int a,b,F,i;
    float C;
    scanf("%d %d",&a,&b);
    if(a>b||a>100||b>100) printf("Invalid.");
    else{
        printf("fahr celsius\\n");//fahr celsius只有一行怎么能写进for里面?完成输出记得换行。
    	for(i=a;i<=b;i=i+2){
            C=5*(i*1.0-32)/9;//把i转化为float
              printf("%d%6.1f\\n",i,C);//三十多是华氏摄氏度,个位小数是摄氏度。
    	}
	}
}

PTA 练习2-13 求N分之一序列前N项和 (15 分)

本题要求编写程序,计算序列 1 + 1/2 + 1/3 + … 的前N项之和。

输入格式:

输入在一行中给出一个正整数N。

输出格式:

在一行中按照“sum = S”的格式输出部分和的值S,精确到小数点后6位。题目保证计算结果不超过双精度范围。

输入样例:

6

输出样例:

sum = 2.450000

#include<stdio.h>
int main(){
    int n;
    double sum=0;
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        sum+=(1.0/i);//1/i不是一个分数(小数)1.0/i才是!!!
    }
        printf("sum = %.6lf",sum);
}

PTA 习题5-2 使用函数求奇数和 (15 分)

本题要求实现一个函数,计算N个整数中所有奇数的和,同时实现一个判断奇偶性的函数。

函数接口定义:

int even( int n );
int OddSum( int List[], int N );

其中函数even将根据用户传入的参数n的奇偶性返回相应值:当n为偶数时返回1,否则返回0。函数OddSum负责计算并返回传入的N个整数List[]中所有奇数的和。

裁判测试程序样例:

#include <stdio.h>
#define MAXN 10
int even( int n );int OddSum( int List[], int N );
int main(){
    int List[MAXN], N, i;
    scanf("%d", &N);
    printf("Sum of ( ");
    for ( i=0; i<N; i++ ) {
        scanf("%d", &List[i]);
        if ( even(List[i])==0 )
            printf("%d ", List[i]);
    }
    printf(") = %d\\n", OddSum(List, N));
    return 0;
}
/* 你的代码将被嵌在这里 */

输入样例:

6
2 -3 7 88 0 15

输出样例:

Sum of ( -3 7 15 ) = 19

int even( int n ){
    if(n%2==0) return 1;
    else
    return 0;
}
int OddSum( int List[], int N )
{
    int i,sum=0;
    for(i=0;i<N;i++)
        if(even(List[i])==0)
           sum+=List[i];
         return sum;
}

PTA 习题5-4 使用函数求素数和 (20 分)

本题要求实现一个判断素数的简单函数、以及利用该函数计算给定区间内素数和的函数。
素数就是只能被1和自身整除的正整数。注意:1不是素数,2是素数。

函数接口定义:

int prime( int p );int PrimeSum( int m, int n );
其中函数prime当用户传入参数p为素数时返回1,否则返回0;函数PrimeSum返回区间[m, n]内所有素数的和。题目保证用户传入的参数m≤n。

裁判测试程序样例:

#include <stdio.h>
#include <math.h>

int prime( int p );
int PrimeSum( int m, int n );

int main(){
    int m, n, p;

    scanf("%d %d", &m, &n);
    printf("Sum of ( ");
    for( p=m; p<=n; p++ ) {
        if( prime(p) != 0 )
            printf("%d ", p);
    }
    printf(") = %d\\n", PrimeSum(m, n));

    return 0;
}
/* 你的代码将被嵌在这里 */

输入样例:

-1 10

输出样例:

Sum of ( 2 3 5 7 ) = 17

int prime( int p )
{
	int i=2,c;
 	if (p <= 1 )
	{
	c=0;
	}
	else if (p == 2)
	{
		c=1;
	}
	else
	{
    for(i=2;i<p;i++)
    	{if(p % i==0)
      		{c=0;
	  		break;}//结束后记得break
	  	else {c=1;}
		}
	}
     return c;
}

int PrimeSum( int m, int n )
{int sum=0,i;
 for(i=m;i<=n;i++)
    if (prime(i)==1)
    sum+=i;

return sum;}

PTA 练习2-15 求简单交错序列前N项和 (15 分)

本题要求编写程序,计算序列 1 - 1/4 + 1/7 - 1/10 + … 的前N项之和。

输入格式:

输入在一行中给出一个正整数N。

输出格式:

在一行中按照“sum = S”的格式输出部分和的值S,精确到小数点后三位。题目保证计算结果不超过双精度范围。

输入样例:

10

输出样例:

sum = 0.819

#include<stdio.h>
int main(){
    float ans=0,z=1;
    int m=1,n,f=1;
    scanf("%d",&n);//怎么就总是忘了加&呢
    for(int i=0;i<n;i++)
    {
        ans=ans+f*(z/m);
        f*=(-1);
        m+=3;
    }
    printf("sum = %.3f",ans);
}

PTA 练习2-15 求简单交错序列前N项和 (15 分)

本题要求编写程序,计算序列 1 - 1/4 + 1/7 - 1/10 + … 的前N项之和。

输入格式:

输入在一行中给出一个正整数N。

输出格式:

在一行中按照“sum = S”的格式输出部分和的值S,精确到小数点后三位。题目保证计算结果不超过双精度范围。

输入样例:

10

输出样例:

sum = 0.819

#include<stdio.h>
int main(){
    float ans=0,z=1;
    int m=1,n,f=1;
    scanf("%d",&n);//怎么就总是忘了加&呢
    for(int i=0;i<n;i++)
    {
        ans=ans+f*(z/m);
        f*=(-1);
        m+=3;
    }
    printf("sum = %.3f",ans);
}

PTA 练习2-18 求组合数 (15 分)

本题要求编写程序,根据公式Cnm=m!(n−m)!n!算出从n个不同元素中取出m个元素(m≤n)的组合数。
建议定义和调用函数fact(n)计算n!,其中n的类型是int,函数类型是double
输入格式:
输入在一行中给出两个正整数m和n(m≤n),以空格分隔。
输出格式:
按照格式“result = 组合数计算结果”输出。题目保证结果在double类型范围内。
输入样例:

2 7

输出样例:

result = 21

#include<stdio.h>
double fact (int);
int main ()
{
    int m,n,i;
    double ans=1;
    scanf("%d %d",&m,&n);
    ans=fact(n)/fact(m)/fact(n-m);//直接把题目给的公式套进来
    printf("result = %.0lf",ans);
}
double fact (int n)
{   double ans=1;
    for(int i=n;i>=1;i--) ans*=i;
    return ans;
}

PTA习题5-6 使用函数输出水仙花数 (20 分)

水仙花数是指一个N位正整数(N≥3),它的每个位上的数字的N次幂之和等于它本身。例如:153=1^3 +5^3 +3^3。 本题要求编写两个函数,一个判断给定整数是否水仙花数,另一个按从小到大的顺序打印出给定区间(m,n)内所有的水仙花数。

函数接口定义:

int narcissistic( int number );
void PrintN( int m, int n );

函数narcissistic判断number是否为水仙花数,是则返回1,否则返回0。
函数PrintN则打印开区间(m, n)内所有的水仙花数,每个数字占一行。题目保证100≤mn≤10000。

裁判测试程序样例:

#include <stdio.h>
int narcissistic( int number );void PrintN( int m, int n );
int main(){
    int m, n;

    scanf("%d %d", &m, &n);
    if ( narcissistic(m) ) printf("%d is a narcissistic number\\n", m);
    PrintN(m, n);
    if ( narcissistic(n) ) printf("%d is a narcissistic number\\n", n);

    return 0;
}
/* 你的代码将被嵌在这里 */

输入样例:

153 400

输出样例:

153 is a narcissistic number
370
371

int narcissistic( int number )
{int d=number,num=number,a=0,b=1,i,j,c=0;
 while(d)
 {d/=10;
  c++;
 }
 for(i=0;i<c;i++)
 {int m=1,o;
  o=num%10;
  for(j=0;j<c;j++)
  m*=o;
  num/=10;
  a+=m;
 }//都是三次
 return (a==number)? 1:0;
}

void PrintN (int m, int n)
{int i;
   for(++m;m<=n;m++)
   {if(narcissistic(m)==1)
	printf("%d\\n",m);
   }
}

C语言经典例题:在一个确定的数组中插入一个数。

#include<stdio.h>
void insert(int a[],int l)
{	int c;
	for(int i=0;i<11;i++)
	{
		if(a[i]>=l){
			c=i;
			for(int j=11;j>i;j--) a[j]=a[j-1];
			break;
			a[c]=l;
		}else a[10]=l;
	}
}
int main()
{
	int i,j,l,p,a[11]={0,1,2,3,4,5,6,7,8,9};
	scanf("%d",&l);
	for (i=0;i<10;i++)
	printf("%d ",a[i]);
	printf("\\n");
	insert(a,l);
	for (i=0;i<11;i++)
	printf("%d ",a[i]);
	return 0;
}

输入样例1:

6

输出样例1:

0 1 2 3 4 5 6 6 7 8 9

输入样例2:

110

输出样例2:

0 1 2 3 4 5 6 7 8 9 110

PTA 习题5-7 使用函数求余弦函数的近似值 (15 分)

本题要求实现一个函数,用下列公式求cos(x)的近似值,精确到最后一项的绝对值小于e:
cos(x)=x0/0!−x2/2!+x4/4!−x6/6!+⋯

函数接口定义:

double funcos( double e, double x );

其中用户传入的参数为误差上限e和自变量x;函数funcos应返回用给定公式计算出来、并且满足误差要求的cos(x)的近似值。输入输出均在双精度范围内。

裁判测试程序样例:

#include <stdio.h>#include <math.h>
double funcos( double e, double x );
int main(){
    double e, x;

    scanf("%lf %lf", &e, &x);
    printf("cos(%.2f) = %.6f\\n", x, funcos(e, x));

    return 0;
}
/* 你的代码将被嵌在这里 */

输入样例:

0.01 -3.14

输出样例:

cos(-3.14) = -0.999899

double funcos( double e, double x )
{   double n1=1,n2=1,n3=1,c=1,p,sum=1;
    for(p=2;n1>e;p+=2)
    {n2=n2*x*x;
    n3=n3*p*(p-1);
    c*=(-1);
    sum=sum+c*n2/n3 ;
    n1=n2/n3;
	}
    return sum;
}

PTA 习题6-2 使用函数求特殊a串数列和 (20 分)

给定两个均不超过9的正整数a和n,要求编写函数求a+aa+aaa++⋯+aa⋯a(n个a)之和。
函数接口定义:

int fn( int a, int n );int SumA( int a, int n );

其中函数fn须返回的是na组成的数字;SumA返回要求的和。
裁判测试程序样例:

#include <stdio.h>
int fn( int a, int n );int SumA( int a, int n );
int main(){
    int a, n;

    scanf("%d %d", &a, &n);
    printf("fn(%d, %d) = %d\\n", a, n, fn(a,n));
    printf("s = %d\\n", SumA(a,n));

    return 0;
}
/* 你的代码将被嵌在这里 */

输入样例:

2 3

输出样例:

fn(2, 3) = 222
s = 246

int fn( int a, int n )
{int i,c=a;
for(i=1;i<n;i++) a=a*10+c;
return a;
}
int SumA( int a, int n )
{
    int i;
    int sum=0;
    for(i=1;i<=n;i++){
        sum=sum+fn(a,i);//递归的思想
    }
    return sum;
}

PTA 习题6-3 使用函数输出指定范围内的完数 (20 分)

本题要求实现一个计算整数因子和的简单函数,并利用其实现另一个函数,输出两正整数m和n(0<m≤n≤10000)之间的所有完数。所谓完数就是该数恰好等于除自身外的因子之和。例如:6=1+2+3,其中1、2、3为6的因子。

函数接口定义:

int factorsum( int number );
void PrintPN( int m, int n );

其中函数factorsum须返回int number的因子和;函数PrintPN要逐行输出给定范围[m, n]内每个完数的因子累加形式的分解式,每个完数占一行,格式为“完数 = 因子1 + 因子2 + … + 因子k”,其中完数和因子均按递增顺序给出。如果给定区间内没有完数,则输出一行“No perfect number”。

裁判测试程序样例:

#include <stdio.h>
int factorsum( int number );void PrintPN( int m, int n );
int main(){
    int m, n;

    scanf("%d %d", &m, &n);
    if ( factorsum(m) == m ) printf("%d is a perfect number\\n", m);
    if ( factorsum(n) == n ) printf("%d is a perfect number\\n", n);
    PrintPN(m, n);

    return 0;
}
/* 你的代码将被嵌在这里 */

输入样例1:

6 30

输出样例1:

6 is a perfect number
6 = 1 + 2 + 3
28 = 1 + 2 + 4 + 7 + 14

输入样例2:

7 25

输出样例2:

No perfect number

int factorsum(int number) {
	int i,sum=0;
    for(i=1;i<number;i++)
    	{if(number%i==0) sum+=i;}
    return sum;
}
void PrintPN(int m, int n) {
	int i,j,k,flag=0;
	for(i=m;i<=n;i++)
	{
		if(i==factorsum(i))
			{flag=1;
			printf("%d = 1",i);
			for(j=2;j<i;j++)
				{if(i%j==0)
				printf(" + %d",j);//加号必须在前面
			}
			printf("\\n");
		}
	}
	if(flag==0)
	printf("No perfect number") ;
}

PTA 习题6-4 使用函数输出指定范围内的Fibonacci数 (20 分)

本题要求实现一个计算Fibonacci数的简单函数,并利用其实现另一个函数,输出两正整数m和n(0<m≤n≤10000)之间的所有Fibonacci数。所谓Fibonacci数列就是满足任一项数字是前两项的和(最开始两项均定义为1)的数列。

函数接口定义:

int fib( int n );
void PrintFN( int m, int n );

其中函数fib须返回第n项Fibonacci数;函数PrintFN要在一行中输出给定范围[m, n]内的所有Fibonacci数,相邻数字间有一个空格,行末不得有多余空格。如果给定区间内没有Fibonacci数,则输出一行“No Fibonacci number”。

裁判测试程序样例:

#include <stdio.h>

int fib( int n );
void PrintFN( int m, int n );

int main(){
    int m, n, t;

    scanf("%d %d %d", &m, &n, &t);
    printf("fib(%d) = %d\\n", t, fib(t));
    PrintFN(m, n);

    return 0;
}

/* 你的代码将被嵌在这里 */

输入样例1:

20 100 7

输出样例1:

fib(7) = 13
21 34 55 89

输入样例2:

2000 2500 8

输出样例2:

fib(8) = 21
No Fibonacci number

int fib(int n)
{
	int n1=1,n2=1,ans;
	if(n<3) return 1;
	else{for(int i=3;i<=n;i++){
			ans=n1+n2;
     		n1=n2;
     		n2=ans;}
		return ans;
	}
}
void PrintFN(int m,int n)
{   int stage[10000],count=0,i=1;
    while(fib(i)<m) i++;
    while(fib(i)<=n)
        stage[count++]= fib(i++);
    if(count==0) puts ("No Fibonacci number");
	else {for(int j=0;j<count-1;j++) printf("%d ",stage[j]);
      printf("%d",stage[count-1]);
     }
}

PTA 习题6-5 使用函数验证哥德巴赫猜想 (20 分)

本题要求实现一个判断素数的简单函数,并利用该函数验证哥德巴赫猜想:任何一个不小于6的偶数均可表示为两个奇素数之和。素数就是只能被1和自身整除的正整数。注意:1不是素数,2是素数。

函数接口定义:

int prime( int p );
void Goldbach( int n );

其中函数prime当用户传入参数p为素数时返回1,否则返回0;函数Goldbach按照格式“n=p+q”输出n的素数分解,其中p≤q均为素数。又因为这样的分解不唯一(例如24可以分解为5+19,还可以分解为7+17),要求必须输出所有解中p最小的解。

裁判测试程序样例:

#include <stdio.h>#include <math.h>
int prime( int p );void Goldbach( int n );
int main(){
    int m, n, i, cnt;

    scanf("%d %d", &m, &n);
    if ( prime(m) != 0 ) printf("%d is a prime number\\n", m);
    if ( m < 6 ) m = 6;
    if ( m%2 ) m++;
    cnt = 0;
    for( i=m; i<=n; i+=2 ) {
        Goldbach(i);
        cnt++;
        if ( cnt%5 ) printf(", ");
        else printf("\\n");
    }

    return 0;
}
/* 你的代码将被嵌在这里 */

输入样例:

89 100

输出样例:

89 is a prime number
90=7+83, 92=3+89, 94=5+89, 96=7+89, 98=19+79
100=3+97,

	int prime( int p )
{int ans=1;
    if(p<2) ans= 0;
    else if(p==2) ans=1;
 else
 {
 for(int i=2;i<=sqrt(p);i++)
    {
     if(p%i==0){
         ans=0;
         break;
        }
    }
 }
 return ans;
 }
void Goldbach( int n )
{
	int a;
	if(n%2==0&&n>=6)
	{for(a=2;a<=n/2;a++)
		if(prime(a)&&prime(n-a))
  	  		{printf("%d=%d+%d",n,a,n-a);
   		 	break;}
	 }
}

程序设计入门——C语言期末考试(辗转相除法)

输入格式:
输入在一行中给出一个分数,分子和分母中间以斜杠"/"分隔,如: 12/34 表示34分之12。分子和分母都是正整数(不包含0)。
(辗转相除法)

//约分最简分式
//先求最大公约数,然后将分子分母同时除以最大公约数;
#include <stdio.h>
int main()
{
	int a,b,n1,n2;
	scanf("%d/%d",&n1,&n2);
    /*如果n1<n2,交换n1和n2的值
    if(n1<n2)
    {
        int t=n1;
        n1=n2;
        n2=t;
    }*/
	a=n1;b=n2;//先储存最后除就不用定义多余的变量
	while(n2!=0)
		{int t=n1%n2;
		n1=n2;
		n2=t;
	}
	printf("%d/%d",a/n1,b/n1);
}

PTA 习题10-7 十进制转换二进制 (15 分)

本题要求实现一个函数,将正整数n转换为二进制后输出。

函数接口定义:

void dectobin( int n );

函数dectobin应在一行中打印出二进制的n。建议用递归实现。

裁判测试程序样例:

#include <stdio.h>
void dectobin( int n );
int main(){
    int n;

    scanf("%d", &n);
    dectobin(n);

    return 0;
}
/* 你的代码将被嵌在这里 */

输入样例:

10

输出样例:

1010

void dectobin(int n) {
    int a[1000], i = 0;
    while (n / 2 != 0)
    {
        a[i++] = n % 2;
        n /= 2;
    }//3/2=1,1/2=0,1就不输出了,所以需要a[i]=n手动输出;
    a[i] = n;
    for (int j = i;j >= 0;j--)
        printf("%d", a[j]);
}

PTA练习8-8 移动字母 (10 分)

本题要求编写函数,将输入字符串的前3个字符移到最后。

函数接口定义:

void Shift( char s[] );

其中char s[]是用户传入的字符串,题目保证其长度不小于3;函数Shift须将按照要求变换后的字符串仍然存在s[]里。

裁判测试程序样例:

#include <stdio.h>#include <string.h>
#define MAXS 10
void Shift( char s[] );
void GetString( char s[] ); /* 实现细节在此不表 */
int main(){
    char s[MAXS];

    GetString(s);
    Shift(s);
    printf("%s\\n", s);

    return 0;
}
/* 你的代码将被嵌在这里 */

输入样例:

abcdef

输出样例:

defabc

void Shift( char s[] )
{   int a[10000],i,n=strlen(s),j;
    for(i=0;i<3;i++)
    {int k=s[0];
     for(j=1;j<n;j++)
      s[j-1]=s[j];
     s[n-1]=k;
    }
}

PTA习题8-1 拆分实数的整数与小数部分 (15 分)

本题要求实现一个拆分实数的整数与小数部分的简单函数。

函数接口定义:

void splitfloat( float x, int *intpart, float *fracpart );

其中x是被拆分的实数(0≤x<10000),*intpart*fracpart分别是将实数x拆分出来的整数部分与小数部分。

裁判测试程序样例:

#include <stdio.h>
void splitfloat( float x, int *intpart, float *fracpart );
int main(){
    float x, fracpart;
    int intpart;

    scanf("%f", &x);
    splitfloat(x, &intpart, &fracpart);
    printf("The integer part is %d\\n", intpart);
    printf("The fractional part is %g\\n", fracpart);

    return 0;
}
/* 你的代码将被嵌在这里 */

输入样例:

2.718

输出样例:

The integer part is 2
The fractional part is 0.718

函数接口定义:

//其中x是被拆分的实数(0≤x<10000),*intpart和*fracpart分别是将实数x拆分出来的整数部分与小数部分。

void splitfloat( float x, int *intpart, float *fracpart ){
 	*intpart = (int)x;
	*fracpart = x- (*intpart);
   }

PTA 习题8-3 数组循环右移 (20 分)

本题要求实现一个对数组进行循环右移的简单函数:一个数组a中存有n(>0)个整数,将每个整数循环向右移m(≥0)个位置,即将a中的数据由(a0a1⋯an−1)变换为(an−m⋯an−1a0a1⋯an−m−1)(最后m个数循环移至最前面的m个位置)。
函数接口定义:

int ArrayShift( int a[], int n, int m );

其中a[]是用户传入的数组;n是数组的大小;m是右移的位数。函数ArrayShift须将循环右移后的数组仍然存在a[]中。
裁判测试程序样例:

#include <stdio.h>#define MAXN 10
int ArrayShift( int a[], int n, int m );
int main(){
    int a[MAXN], n, m;
    int i;

    scanf("%d %d", &n, &m);
    for ( i = 0; i < n; i++ ) scanf("%d", &a[i]);

    ArrayShift(a, n, m);

    for ( i = 0; i < n; i++ ) {
        if (i != 0) printf(" ");
        printf("%d", a[i]);
    }
    printf("\\n");

    return 0;
}

/* 你的代码将被嵌在这里 */
输入样例:

6 2
1 2 3 4 5 6

输出样例:

5 6 1 2 3 4

int ArrayShift( int a[], int n, int m )
{
    for (int i=0;i<m;i++)
    {int k=a[n-1];
        for (int j=n-1;j>=1;j--)//a[10]的下标是0123456789不存在a[10]。
            a[j]=a[j-1];
            a[0]=k;
	}
}

PTA 习题8-4 报数 (20 分)

报数游戏是这样的:有n个人围成一圈,按顺序从1到n编好号。从第一个人开始报数,报到m(<n)的人退出圈子;下一个人从1开始报数,报到m的人退出圈子。如此下去,直到留下最后一个人。
本题要求编写函数,给出每个人的退出顺序编号。

函数接口定义:

void CountOff( int n, int m, int out[] );

其中n是初始人数;m是游戏规定的退出位次(保证为小于n的正整数)。函数CountOff将每个人的退出顺序编号存在数组out[]中。因为C语言数组下标是从0开始的,所以第i个位置上的人是第out[i-1]个退出的。

裁判测试程序样例:

#include <stdio.h>#define MAXN 20
void CountOff( int n, int m, int out[] );
int main(){
    int out[MAXN], n, m;
    int i;

    scanf("%d %d", &n, &m);
    CountOff( n, m, out );
    for ( i = 0; i < n; i++ )
        printf("%d ", out[i]);
    printf("\\n");

    return 0;
}
/* 你的代码将被嵌在这里 */

输入样例:

11 3

输出样例:

4 10 1 7 5 2 11 9 3 6 8

void CountOff( int n, int m, int out[] )
{
int a[MAXN],i,j=0,p=0,count=0;
    for(i=0;i<n;i++) a[i]=i+1;
    i=0;
    while(count<n)
    {
        if(a[i]!=0) p++;
        if(p==m){
            j++;
            out[i]=j;
            p=0;
            a[i]=0;
            count++;
        }
        i++;
        if(i==n) i=0;
    }
}

PTA习题8-5 使用函数实现字符串部分复制 (20 分)

本题要求编写函数,将输入字符串t中从第m个字符开始的全部字符复制到字符串s中。

函数接口定义:

void strmcpy( char *t, int m, char *s );

函数strmcpy将输入字符串char *t中从第m个字符开始的全部字符复制到字符串char *s中。若m超过输入字符串的长度,则结果字符串应为空串。

裁判测试程序样例:

#include <stdio.h>
#define MAXN 20
void strmcpy( char *t, int m, char *s );
void ReadString( char s[] ); /* 由裁判实现,略去不表 */
int main(){
    char t[MAXN], s[MAXN];
    int m;

    scanf("%d\\n", &m);
    ReadString(t);
    strmcpy( t, m, s );
    printf("%s\\n", s);

    return 0;
}
/* 你的代码将被嵌在这里 */

输入样例:

7
happy new year

输出样例:

new year

#include<string.h>
void strmcpy( char *t, int m, char *s )
{
	int n,i,j=0,k;
    meset(char *s,0,strlen(s));
    //for(i=0;i<strlen(s);i++) s[i]=0;
    n=strlen(t);
    if(m>n) *s=NULL;
    else {for(i=m-1;i<=n;i++)
        s[j++]=t[i];
    }
}

PTA 习题8-6 删除字符 (20 分)

本题要求实现一个删除字符串中的指定字符的简单函数。

函数接口定义:

void delchar( char *str, char c );

其中char *str是传入的字符串,c是待删除的字符。函数delchar的功能是将字符串str中出现的所有c字符删除。

裁判测试程序样例:

#include <stdio.h>#define MAXN 20
void delchar( char *str, char c );
void ReadString( char s[] ); /* 由裁判实现,略去不表 */

int main(){
    char str[MAXN], c;

    scanf("%c\\n", &c);
    ReadString(str);
    delchar(str, c);
    printf("%s\\n", str);

    return 0;
}
/* 你的代码将被嵌在这里 */

输入样例:

a
happy new year

输出样例:

hppy new yer


 void delchar( char *str, char c ){
      int n=strlen(str);
      for(int i=0;i<n;i++)
      {while(str[i]==c) {for(int j=i;j<n;j++)
                       str[j]=str[j+1];
                     }
      }
 }

/*为什么要用while:
while()
{
.....
}
如果while后边括号内的表达式为真,那么执行{}内的语句,然后再判断while后边()的表达式是否为真,如果是真,再次执行{}内的语句,直到()内的条件为假。
if()
{
.......
}
语句A
.........
如果if后边()内为真,执行{}内语句,执行完之后执行下边语句A。如果为假直接执行语句A
for(i=0;i<10;i++)
{
.......
}
语句A
......
表示从i=0到i<10执行{}内的语句。
i=0是初始化,i<10是执行的条件,只有满足了这个条件才执行,如果不满足,就跳过,执行语句A以及后边的语句;
for语句可以实现while语句的功能,
例如
Int i=0;
while(i<10)
{
...........
i++;//类似的语句必须出现,否则无法满足退出条件
....
}
for(;;)
{
}
只是这样就永远执行下边的语句,当然也可以用break;来退出
for(;;)
{
........
if(i>10)
{
break;
}
i++;
........
} */

PTA 习题8-8 判断回文字符串 (20 分)

本题要求编写函数,判断给定的一串字符是否为“回文”。所谓“回文”是指顺读和倒读都一样的字符串。如“XYZYX”和“xyzzyx”都是回文。

函数接口定义:

bool palindrome( char *s );

函数palindrome判断输入字符串char *s是否为回文。若是则返回true,否则返回false

裁判测试程序样例:

#include <stdio.h>#include <string.h>
#define MAXN 20typedef enum {false, true} bool;
bool palindrome( char *s );
int main(){
    char s[MAXN];

    scanf("%s", s);
    if ( palindrome(s)==true )
        printf("Yes\\n");
    else
        printf("No\\n");
    printf("%s\\n", s);

    return 0;
}
/* 你的代码将被嵌在这里 */

输入样例1:

thisistrueurtsisiht

输出样例1:

Yes
thisistrueurtsisiht

输入样例2:

thisisnottrue

输出样例2:

Nothisisnottrue

bool palindrome( char *s )
{
	int i,len=strlen(s),ans=true;
    if(len%2==0)
    {    for(i=0;i<(len/2);i++)
            if(s[i]!=s[len-1-i]) ans = false;}
    		else{for(i=0;i<len/2;i++)
        	if(s[i]!=s[len-1-i]) ans = false;}
          return ans;
}
//非常简洁,哈哈哈哈!

PTA 习题9-2 计算两个复数之积 (15 分)

本题要求实现一个计算复数之积的简单函数。

函数接口定义:

struct complex multiply(struct complex x, struct complex y);

其中struct complex是复数结构体,其定义如下:

struct complex{
    int real;
    int imag;
};

裁判测试程序样例:

#include <stdio.h>
struct complex{
    int real;
    int imag;
};
struct complex multiply(struct complex x, struct complex y);
int main(){
    struct complex product, x, y;

    scanf("%d%d%d%d", &x.real, &x.imag, &y.real, &y.imag);
    product = multiply(x, y);
    printf("(%d+%di) * (%d+%di) = %d + %di\\n",
            x.real, x.imag, y.real, y.imag, product.real, product.imag);

    return 0;
}
/* 你的代码将被嵌在这里 */

输入样例:

3 4 5 6

输出样例:

(3+4i) * (5+6i) = -9 + 38i

struct complex multiply(struct complex x, struct complex y)
{   struct complex product;//struct complex相当于int

    product.real=x.real*y.real-x.imag*y.imag;
    product.imag=x.real*y.imag+x.imag*y.real;
    return product;
}

PTA 习题9-6 按等级统计学生成绩 (20 分)

本题要求实现一个根据学生成绩设置其等级,并统计不及格人数的简单函数。

函数接口定义:

int set_grade( struct student *p, int n );

其中p是指向学生信息的结构体数组的指针,该结构体的定义为:

struct student{
    int num;
    char name[20];
    int score;
    char grade;
};

n是数组元素个数。学号num、姓名name和成绩score均是已经存储好的。set_grade函数需要根据学生的成绩score设置其等级grade。等级设置:85-100为A,70-84为B,60-69为C,0-59为D。同时,set_grade还需要返回不及格的人数。

裁判测试程序样例:

#include <stdio.h>#define MAXN 10
struct student{
    int num;
    char name[20];
    int score;
    char grade;
};
int set_grade( struct student *p, int n );
int main(){   struct student stu[MAXN], *ptr;//这里定义了学生人数;
    int n, i, count;

    ptr = stu;
    scanf("%d\\n", &n);
    for(i = 0; i < n; i++){
       scanf("%d%s%d", &stu[i].num, stu[i].name, &stu[i].score);
    }
   count = set_grade(ptr, n);
   printf("The count for failed (<60): %d\\n", count);
   printf("The grades:\\n");
   for(i = 0; i < n; i++)
       printf("%d %s %c\\n", stu[i].num, stu[i].name, stu[i].grade);
    return 0;
}
/* 你的代码将被嵌在这里 */

输入样例:

10
31001 annie 85
31002 bonny 75
31003 carol 70
31004 dan 84
31005 susan 90
31006 paul 69
31007 pam 60
31008 apple 50
31009 nancy 100
31010 bob 78

输出样例:

The count for failed (<60): 1
The grades:
31001 annie A
31002 bonny B
31003 carol B
31004 dan B
31005 susan A
31006 paul C
31007 pam C
31008 apple D
31009 nancy A
31010 bob B

int set_grade( struct student *p, int n )
{
    int c=0;
    for(int i=0;i<n;i++)
    {
   	 	if(p[i].score>=85&&p[i].score<=100) p[i].grade='A';
    	else if(p[i].score>=70&&p[i].score<=84) p[i].grade='B';
    	else if(p[i].score>=60&&p[i].score<=69) p[i].grade='C';
    	else if(p[i].score>=0&&p[i].score<=59) {p[i].grade='D';
                                               c++;}
    }
     return c;
}

PTA 练习10-1 使用递归函数计算1到n之和 (10 分)

本题要求实现一个用递归计算1+2+3+…+n的和的简单函数。

函数接口定义:

int sum( int n );

该函数对于传入的正整数n返回1+2+3+…+n的和;若n不是正整数则返回0。题目保证输入输出在长整型范围内。建议尝试写成递归函数。

裁判测试程序样例:

#include <stdio.h>
int sum( int n );
int main(){
    int n;

    scanf("%d", &n);
    printf ("%d\\n", sum(n));

    return 0;
}
/* 你的代码将被嵌在这里 */

输入样例1:

10

输出样例1:

55

输入样例2:

0

输出样例2:

0

int sum( int n )
{	int ans;
    if(n==1)
    {
        ans=1;
    }else if(n<=0){
                   ans=0;
    }else {ans = n+sum(n-1);}
	return ans;
}
//小递归很简单。

PTA 习题10-1 判断满足条件的三位数 (15 分)

本题要求实现一个函数,统计给定区间内的三位数中有两位数字相同的完全平方数(如144、676)的个数。

函数接口定义:

int search( int n );

其中传入的参数int n是一个三位数的正整数(最高位数字非0)。函数search返回[101, n]区间内所有满足条件的数的个数。

裁判测试程序样例:

#include <stdio.h>#include <math.h>
int search( int n );
int main(){
    int number;

    scanf("%d",&number);
    printf("count=%d\\n",search(number));

    return 0;
}

int search( int n )
{
    int i;
    int a,b,c;
    int temp=0;
    for(i=101;i<=n;i++)
    {
        a=i%10;
        c=i/100;
        b=i/10-10*c;
        if((a==b)||(a==c)||(b==c))
        {
            for(int j=10;j<=i/2;j++)
            if(j*j==i) temp++;//要累加数字,temp=1就错了。
            //int t=sqrt(i);
            //if(t*t==i) temp++;也可以
        }
    }
    return temp;
}

PTA 习题10-3 递归实现指数函数 (15 分)

本题要求实现一个计算xn(n≥1)的函数。

函数接口定义:

double calc_pow( double x, int n );

函数calc_pow应返回x的n次幂的值。建议用递归实现。题目保证结果在双精度范围内。

裁判测试程序样例:

#include <stdio.h>
double calc_pow( double x, int n );
int main(){
    double x;
    int n;

    scanf("%lf %d", &x, &n);
    printf("%.0f\\n", calc_pow(x, n));

    return 0;
}
/* 你的代码将被嵌在这里 */

输入样例:

2 3

输出样例:

8

double calc_pow( double x, int n )
{   int ans=0;
    if(n==1) ans=x;
    else ans=x*calc_pow(x,n-1);
    return ans;
}

PTA 习题10-4 递归求简单交错幂级数的部分和 (15 分)

本题要求实现一个函数,计算下列简单交错幂级数的部分和:
f(x,n)=x−x2+x3−x4+⋯+(−1)n−1xn

函数接口定义:

double fn( double x, int n );

其中题目保证传入的n是正整数,并且输入输出都在双精度范围内。函数fn应返回上述级数的部分和。建议尝试用递归实现。

裁判测试程序样例:

#include <stdio.h>
double fn( double x, int n );
int main(){
    double x;
    int n;

    scanf("%lf %d", &x, &n);
    printf("%.2f\\n", fn(x,n));

    return 0;
}
/* 你的代码将被嵌在这里 */

输入样例:

0.5 12

输出样例:

0.33

double fn(double x, int n)
{
    double ans = 0;
    if(n==1){ans=x;}
    else{ans=pow(-1,n-1)*pow(x,n)+fn(x,n-1);}
    return ans;
}

PTA 习题10-8 递归实现顺序输出整数 (15 分)

本题要求实现一个函数,对一个整数进行按位顺序输出。

函数接口定义:

void printdigits( int n );

函数printdigits应将n的每一位数字从高位到低位顺序打印出来,每位数字占一行。

裁判测试程序样例:

#include <stdio.h>
void printdigits( int n );
int main(){
    int n;

    scanf("%d", &n);
    printdigits(n);

    return 0;
}
/* 你的代码将被嵌在这里 */

输入样例:

12345

输出样例:

1
2
3
4
5

void printdigits(int n)
{
    if (n < 10) printf("%d\\n", n);
    else {
        printdigits(n / 10);
        printf("%d\\n", n % 10); //123456-12345-1234-123-12-1  然后输出1-1  12%10-2 123%10-3  .....输出1 2 3 4 5 6
    }
}//如果交换        123456  输出  6 5 4 3 2 1

PTA 习题11-1 输出月份英文名 (15 分)

本题要求实现函数,可以返回一个给定月份的英文名称。

函数接口定义:

char *getmonth( int n );

函数getmonth应返回存储了n对应的月份英文名称的字符串头指针。如果传入的参数n不是一个代表月份的数字,则返回空指针NULL。

裁判测试程序样例:

#include <stdio.h>
char *getmonth( int n );
int main(){
    int n;
    char *s;

    scanf("%d", &n);
    s = getmonth(n);
    if ( s==NULL ) printf("wrong input!\\n");
    else printf("%s\\n", s);

    return 0;
}
/* 你的代码将被嵌在这里 */

输入样例1:

5

输出样例1:

May

输入样例2:

15

输出样例2:

wrong input!


char *getmonth( int n )
{
	static	char month[100][100]={"January","February","March","April","May","June","July","August","September","October","November","December"};
	if(n>0&&n<13)
	return &month[n-1][0];
	else return NULL;
}

PTA 习题11-2 查找星期 (15 分)

本题要求实现函数,可以根据下表查找到星期,返回对应的序号。

序号	星期
0	Sunday
1	Monday
2	Tuesday
3	Wednesday
4	Thursday
5	Friday
6	Saturday

函数接口定义:

int getindex( char *s );

函数getindex应返回字符串s序号。如果传入的参数s不是一个代表星期的字符串,则返回-1。

裁判测试程序样例:

#include <stdio.h>#include <string.h>
#define MAXS 80
int getindex( char *s );
int main(){
    int n;
    char s[MAXS];

    scanf("%s", s);
    n = getindex(s);
    if ( n==-1 ) printf("wrong input!\\n");
    else printf("%d\\n", n);

    return 0;
}
/* 你的代码将被嵌在这里 */

输入样例1:

Tuesday

输出样例1:

2

输入样例2:

today

输出样例2:

wrong input!

int getindex( char *s )
{
    int ans;
    char *day[7]={"Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"};
    for (int i=0;i<=6;i++)
    if(strcmp (s,day[i])==0)  {ans=i;
                                break;}
    else ans=-1;
    return ans;
}

PTA习题11-3 计算最长的字符串长度 (15 分)

本题要求实现一个函数,用于计算有n个元素的指针数组s中最长的字符串的长度。

函数接口定义:

int max_len( char *s[], int n );

其中n个字符串存储在s[]中,函数max_len应返回其中最长字符串的长度。

裁判测试程序样例:

#include <stdio.h>#include <string.h>#include <stdlib.h>
#define MAXN 10#define MAXS 20
int max_len( char *s[], int n );
int main(){
    int i, n;
    char *string[MAXN] = {NULL};

    scanf("%d", &n);
    for(i = 0; i < n; i++) {
        string[i] = (char *)malloc(sizeof(char)*MAXS);
        scanf("%s", string[i]);
    }
    printf("%d\\n", max_len(string, n));

    return 0;
}
/* 你的代码将被嵌在这里 */

输入样例:

4
blue
yellow
red
green

输出样例:

6

int max_len( char *s[], int n ){
    int max=0;
    for(int i=0;i<n;i++)
    {
        if(strlen(s[max])<strlen(s[i])) max=i;//用max=0比递增的i,不必用i和i+1去比
    }
    return strlen(s[max]);
}

PTA 习题11-4 字符串的连接 (15 分)

本题要求实现一个函数,将两个字符串连接起来。

函数接口定义:

char *str_cat( char *s, char *t );

函数str_cat应将字符串t复制到字符串s的末端,并且返回字符串s的首地址。

裁判测试程序样例:

#include <stdio.h>#include <string.h>
#define MAXS 10
char *str_cat( char *s, char *t );
int main(){
    char *p;
    char str1[MAXS+MAXS] = {'\\0'}, str2[MAXS] = {'\\0'};

    scanf("%s%s", str1, str2);
    p = str_cat(str1, str2);
    printf("%s\\n%s\\n", p, str1);

    return 0;
}
/* 你的代码将被嵌在这里 */

输入样例:

abc
def

输出样例:

abcdef
abcdef

char *str_cat( char *s, char *t ){
    int len1=strlen(s),len2=strlen(t);
    for(int i=0;i<len2;i++)
    {
        s[len1+i]=t[i];
    }
    return s;
}
/*
/*函数str_cat应将字符串t复制到字符串s的末端,并且返回字符串s的首地址。*/
char *str_cat( char *s, char *t )
{
    char *p;
    p=strcat(s,t);//函数strcat的功能是把两个字符串连接成一个字符串
    return p;
}*/

习题11-6 查找子串 (20 分)

本题要求实现一个字符串查找的简单函数。

函数接口定义:

char *search( char *s, char *t );

函数search在字符串s中查找子串t,返回子串ts中的首地址。若未找到,则返回NULL。

裁判测试程序样例:

#include <stdio.h>#define MAXS 30
char *search(char *s, char *t);void ReadString( char s[] ); /* 裁判提供,细节不表 */
int main(){
    char s[MAXS], t[MAXS], *pos;

    ReadString(s);
    ReadString(t);
    pos = search(s, t);
    if ( pos != NULL )
        printf("%d\\n", pos - s);
    else
        printf("-1\\n");

    return 0;
}
/* 你的代码将被嵌在这里 */

输入样例1:

The C Programming Language
ram

输出样例1:

10

输入样例2:

The C Programming Languagebored

输出样例2:

-1

#include <string.h>
char *search( char *s, char *t )
{
    int k=0,j,i;
    char*p=NULL;
    for(i=0;i<strlen(s);i++){
        j=i;
        while (s[j]==t[k]) {k++;j++;}
        if(k>=strlen(t)) return &s[i];
        k=0;//防止存在多个t吗?????
    }
    return p;
}

PTA 习题11-7 奇数值结点链表 (20 分)

本题要求实现两个函数,分别将读入的数据存储为单链表、将链表中奇数值的结点重新组成一个新的链表。链表结点定义如下:

struct ListNode {
    int data;
    ListNode *next;
};

函数接口定义:

struct ListNode *readlist();struct ListNode *getodd( struct ListNode **L );

函数readlist从标准输入读入一系列正整数,按照读入顺序建立单链表。当读到−1时表示输入结束,函数应返回指向单链表头结点的指针。
函数getodd将单链表L中奇数值的结点分离出来,重新组成一个新的链表。返回指向新链表头结点的指针,同时将L中存储的地址改为删除了奇数值结点后的链表的头结点地址(所以要传入L的指针)。

裁判测试程序样例:

#include <stdio.h>#include <stdlib.h>
struct ListNode {
    int data;
    struct ListNode *next;
};
struct ListNode *readlist();struct ListNode *getodd( struct ListNode **L );void printlist( struct ListNode *L ){
     struct ListNode *p = L;
     while (p) {
           printf("%d ", p->data);
           p = p->next;
     }
     printf("\\n");
}
int main(){
    struct ListNode *L, *Odd;
    L = readlist();
    Odd = getodd(&L);
    printlist(Odd);
    printlist(L);

    return 0;
}
/* 你的代码将被嵌在这里 */

输入样例:

1 2 2 3 4 5 6 7 -1

输出样例:

1 3 5 7
2 2 4 6

struct ListNode *readlist()
{
    struct ListNode *head=NULL,*tail=head,*p;
    int n=1;
    while(n!=-1){
        scanf("%d",&n);
        if(n!=-1){
            p=(struct ListNode*)malloc(sizeof(struct ListNode));
            p->data=n;
            if(head==NULL) head=p;//双等于
            else tail->next=p;//tailnext
            tail=p;
        }
    }
    return head;//记得return
}

struct ListNode *getodd( struct ListNode **L )
{
    struct ListNode *h1=NULL,*h2=NULL,*tail1=h1,*tail2=h2,*p;
    int a;
    while(*L){//用while
        a=(*L)->data;//括号
        p=(struct ListNode*)malloc(sizeof(struct ListNode));
        p->next=NULL;
        p->data=a;//把if和else里的这一句提出来
        if(a%2){
            //p->data=a;
            if(h1==NULL) h1=p;
            else tail1->next=p;
            tail1=p;
        }
        else
        {
           // p->data=a;
            if(h2==NULL) h2=p;
            else tail2->next=p;
            tail2=p;
        }
        (*L)=(*L)->next;
    }
    *L=h2;
    return h1;
}

牛客题霸-算法篇题目描述

写出一个程序,接受一个字符串,然后输出该字符串反转后的字符串。(字符串长度不超过1000)

示例1

输入

"abcd"

返回值

"dcba"

void swap(int x,int y){
    int temp=x;
    x=y;
    y=temp;
}
char* solve(char* str ) {
    int i=0,j=strlen(str)-1;
    while(i<j) swap(str[i++],str[j--]);
    return str;

}

牛客题霸-算法篇题目描述

给定一个字符串,请编写一个函数判断该字符串是否回文。如果回文请返回true,否则返回false

示例1

输入

"absba"

返回值

true

示例2

输入

"ranko"

返回值

false

示例3

输入

"yamatomaya"

返回值

false

示例4

输入

"a"

返回值

true

备注:

字符串长度不大于1000000,且仅由小写字母组成

#include <stdbool.h>
bool judge(char* str ) {
    int i=0,j=strlen(str)-1;
    while(i<j) if(str[i++]!=str[j--]) return false;
    return true;
}//只返回一次所以要用!=,并且不能使用else。

LeetCode 面试题 17.16. 按摩师

一个有名的按摩师会收到源源不断的预约请求,每个预约都可以选择接或不接。在每次预约服务之间要有休息时间,因此她不能接受相邻的预约。给定一个预约请求序列,替按摩师找到最优的预约集合(总预约时间最长),返回总的分钟数。
注意:本题相对原题稍作改动

示例 1:

输入: [1,2,3,1]
输出: 4
解释: 选择 1 号预约和 3 号预约,总时长 = 1 + 3 = 4。

示例 2:

输入: [2,7,9,3,1]
输出: 12
解释: 选择 1 号预约、 3 号预约和 5 号预约,总时长 = 2 + 9 + 1 = 12。

示例 3:

输入: [2,1,4,5,3,1,1,3
]输出: 12
解释: 选择 1 号预约、 3 号预约、 5 号预约和 8 号预约,总时长 = 2 + 4 + 3 + 3 = 12。

/*解题思路

int massage(int* nums, int numsSize){//numsSize 数组大小,最后需返回数组大小numsSize
    int t1=0,t2=0;
    for(int i=0;i<numsSize;i++){
        int t=fmax(t1+nums[i],t2);
        t1=t2;
        t2=t;
    }
    return t2;
}//**假设第i次接受预约,与上一次比较那个数值更大,然后取更大的值保存下来。如果第i次接受预约,那么第i+1次必然是不接受预约的,如果第i次不接受预约,那么第i+1次可能接受预约,也有可能连续两次都不接受预约,从中选取最大值保存下来,最后返回最后一次比较的结果。**//

LeetCode 1480. 一维数组的动态和

给你一个数组 nums 。数组「动态和」的计算公式为:runningSum[i] = sum(nums[0]…nums[i])
请返回 nums 的动态和。

示例 1:

输入:nums = [1,2,3,4]
输出:[1,3,6,10]
解释:动态和计算过程为 [1, 1+2, 1+2+3, 1+2+3+4] 。

示例 2:

输入:nums = [1,1,1,1,1]
输出:[1,2,3,4,5]
解释:动态和计算过程为 [1, 1+1, 1+1+1, 1+1+1+1, 1+1+1+1+1] 。

示例 3:

输入:nums = [3,1,2,10,1]
输出:[3,4,6,16,17]

提示:

1 <= nums.length <= 1000
-10^6 <= nums[i] <= 10^6

int* runningSum(int* nums, int numsSize, int* returnSize){//返回数组的大小
    if( numsSize==0){
        *returnSize = 0;
        return NULL;

    }
    for(int i=1;i<numsSize;i++){
        nums[i]+=nums[i-1];
    }
    *returnSize= numsSize;
    return nums;
}

剑指 Offer 24. 反转链表

定义一个函数,输入一个链表的头节点,反转该链表并输出反转后链表的头节点。

示例:

输入: 1->2->3->4->5->NULL
输出: 5->4->3->2->1->NULL

限制:

0 <= 节点个数 <= 5000

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */

struct ListNode* reverseList(struct ListNode* head){
    struct ListNode* pre=NULL;//转完后最开始的head->next=NULL嘛
    struct ListNode* cur=head;
    while(cur!=NULL){
        struct ListNode* next=cur->next;
        cur->next=pre;//不是pre=cur->next!!!要使next指向pre!!
        pre=cur;
        cur=next;
    }
    return pre;//此时cur为NULL,题目要求返回值开头为5.
}//动画演示很清晰.

```java
/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode reverseList(ListNode head) {
        ListNode prev = null;
        ListNode curr = head;
        while(curr != null){
            ListNode next = curr.next;
            curr.next = prev;
            prev = curr;
            curr = next;
        }
        return prev;
    }
}

PTA实验11-2-1 建立学生信息链表 (20 分)

本题要求实现一个将输入的学生成绩组织成单向链表的简单函数。

函数接口定义:

void input();

该函数利用scanf从输入中获取学生的信息,并将其组织成单向链表。链表节点结构定义如下:

struct stud_node {
    int              num;      /*学号*/
    char             name[20]; /*姓名*/
    int              score;    /*成绩*/
    struct stud_node *next;    /*指向下个结点的指针*/
};

单向链表的头尾指针保存在全局变量headtail中。
输入为若干个学生的信息(学号、姓名、成绩),当输入学号为0时结束。

裁判测试程序样例:

#include <stdio.h>#include <stdlib.h>#include <string.h>
struct stud_node {
     int    num;
     char   name[20];
     int    score;
     struct stud_node *next;
};struct stud_node *head, *tail;
void input();
int main(){
    struct stud_node *p;

    head = tail = NULL;
    input();
    for ( p = head; p != NULL; p = p->next )
        printf("%d %s %d\\n", p->num, p->name, p->score);

    return 0;
}
/* 你的代码将被嵌在这里 */

输入样例:

1 zhang 78
2 wang 80
3 li 75
4 zhao 85
0

输出样例:

1 zhang 78
2 wang 80
3 li 75
4 zhao 85

void input(){
    int number;
    struct stud_node *p;
    scanf("%d",&number);
    while(number!=0){//要使用number,不可以直接用p->num;
        p=(struct stud_node *)malloc(sizeof(struct stud_node));//记得加struct,这句话要写在while里面,每次都需要申请新的空间
        p->num=number;
        if(head==NULL) head=p;//双等于!!
        else tail->next=p;//这里完成了下一节点的转换
        tail=p;
        tail->next=NULL;
        //scanf("%s %d %d",&p->name,&p->num,number);为什么写在一行会报错???
        scanf("%s %d",&p->name,&p->score);
        scanf("%d",&number);
    }
}

PTA 实验11-2-2 学生成绩链表处理 (20 分)

本题要求实现两个函数,一个将输入的学生成绩组织成单向链表;另一个将成绩低于某分数线的学生结点从链表中删除。

函数接口定义:

struct stud_node *createlist();
struct stud_node *deletelist( struct stud_node *head, int min_score );

函数createlist利用scanf从输入中获取学生的信息,将其组织成单向链表,并返回链表头指针。链表节点结构定义如下:

struct stud_node {
    int              num;      /*学号*/
    char             name[20]; /*姓名*/
    int              score;    /*成绩*/
    struct stud_node *next;    /*指向下个结点的指针*/
};

输入为若干个学生的信息(学号、姓名、成绩),当输入学号为0时结束。
函数deletelist从以head为头指针的链表中删除成绩低于min_score的学生,并返回结果链表的头指针。

裁判测试程序样例:

#include <stdio.h>#include <stdlib.h>
struct stud_node {
     int    num;
     char   name[20];
     int    score;
     struct stud_node *next;
};
struct stud_node *createlist();struct stud_node *deletelist( struct stud_node *head, int min_score );
int main(){
    int min_score;
    struct stud_node *p, *head = NULL;

    head = createlist();
    scanf("%d", &min_score);
    head = deletelist(head, min_score);
    for ( p = head; p != NULL; p = p->next )
        printf("%d %s %d\\n", p->num, p->name, p->score);

    return 0;
}
/* 你的代码将被嵌在这里 */

输入样例:

1 zhang 78
2 wang 80
3 li 75
4 zhao 85
0
80

输出样例:

2 wang 80
4 zhao 85

struct stud_node* createlist() {
    int number;
    scanf("%d", &number);
    struct stud_node* p,*head, * tail = head = NULL;
    while (number != 0) {
        p = (struct stud_node*)malloc(sizeof(struct stud_node));
        p->num = number;
        if (head == NULL) head = p;
        else tail->next = p;
        tail=p;
        tail->next = NULL;
        scanf("%s %d", &p->name, &p->score);
        scanf("%d", &number);
    }
    return head;
}//详见https://blog.csdn.net/qq_53749266/article/details/115046995
/*定义在外界才是全局变量!!
struct stud_node {
     int    num;
     char   name[20];
     int    score;
     struct stud_node *next;
};
struct stud_node *head, *tail;
*/
struct stud_node *deletelist(struct stud_node *head,int min_score)
{
    struct stud_node *p,*tail;
    //if(head==NULL) return NULL;放到下面去防止删空了!!
    while(head!=NULL&&head->score<min_score) {//如果前面没有了head==NULL,这里要加上写head还要!=NULL才行!!!
        p=head;
        head=head->next;
        free(p);
    }
    if(head==NULL) return NULL;
    p=head;
    tail=p->next;
    while(tail){
        if(tail->score<min_score){
            p->next=tail->next;//连接前一节与之后一节,用p就够了,head永远在那里。
            free(tail);
        }else p=tail;//p前进,永远让p小于tail一节。
        tail=tail->next;
    }
    return head;
}

实验11-2-3 逆序数据建立链表 (20 分)

本题要求实现一个函数,按输入数据的逆序建立一个链表。

函数接口定义:

struct ListNode *createlist();

函数createlist利用scanf从输入中获取一系列正整数,当读到−1时表示输入结束。按输入数据的逆序建立一个链表,并返回链表头指针。链表节点结构定义如下:

struct ListNode {
    int data;
    struct ListNode *next;
};

裁判测试程序样例:

#include <stdio.h>
#include <stdlib.h>
struct ListNode {
    int data;
    struct ListNode *next;
};
struct ListNode *createlist();
int main(){
    struct ListNode *p, *head = NULL;

    head = createlist();
    for ( p = head; p != NULL; p = p->next )
        printf("%d ", p->data);
    printf("\\n");

    return 0;
}
/* 你的代码将被嵌在这里 */

输入样例:

1 2 3 4 5 6 7 -1

输出样例:

7 6 5 4 3 2 1

struct ListNode *createlist(){
    int number;
    scanf("%d",&number);
    struct ListNode *p,*head=NULL;//head一开始一定是NULL!
    while(number!=-1){
        p=(struct ListNode *)malloc(sizeof(struct ListNode ));
        p->data=number;
        if(head==NULL)
        {
        	head=p;
        	head->next=NULL;
        }
        else
        	p->next=head;//永远得是前一个指向后一个
        head=p;//头后移
        scanf("%d",&number);
    }
    return head;
}

PTA 实验11-2-4 删除单链表偶数节点 (20 分)

本题要求实现两个函数,分别将读入的数据存储为单链表、将链表中偶数值的结点删除。链表结点定义如下:

struct ListNode {
    int data;
    struct ListNode *next;
};

函数接口定义:

struct ListNode *createlist();
struct ListNode *deleteeven( struct ListNode *head );

函数createlist从标准输入读入一系列正整数,按照读入顺序建立单链表。当读到−1时表示输入结束,函数应返回指向单链表头结点的指针。
函数deleteeven将单链表head中偶数值的结点删除,返回结果链表的头指针。

裁判测试程序样例:

#include <stdio.h>#include <stdlib.h>
struct ListNode {
    int data;
    struct ListNode *next;
};
struct ListNode *createlist();struct ListNode *deleteeven( struct ListNode *head );void printlist( struct ListNode *head ){
     struct ListNode *p = head;
     while (p) {
           printf("%d ", p->data);
           p = p->next;
     }
     printf("\\n");
}
int main(){
    struct ListNode *head;

    head = createlist();
    head = deleteeven(head);
    printlist(head);

    return 0;
}
/* 你的代码将被嵌在这里 */

输入样例:

1 2 2 3 4 5 6 7 -1

输出样例:

1 3 5 7

struct ListNode *createlist()
{
    int number;
    struct ListNode *p,*head,*tail=head=NULL;
    scanf("%d",&number);
    while(number!=-1){
        p=(struct ListNode *)malloc(sizeof(struct ListNode ));
        p->data=number;
        if(head==NULL) head=p;
        else tail->next=p;
        tail=p;
        tail->next=NULL;//别忘了这一句
        scanf("%d",&number);
    }
return head;
}

struct ListNode *deleteeven( struct ListNode *head )
{
    struct ListNode *p,*tail;
    while(head&&head->data%2==0){
        p=head;
        head=head->next;
        free(p);
    }
    if(head==NULL) return NULL;
    p=head;
    tail=head->next;
    while(tail){
        if(tail->data%2==0){
            p->next=tail->next;
            free(tail);
        }else p=tail;
        tail=p->next;
    }
    return head;
}

PTA 习题11-8 单链表结点删除 (20 分) 实验11-2-8 单链表结点删除 (20 分)

本题要求实现两个函数,分别将读入的数据存储为单链表、将链表中所有存储了某给定值的结点删除。链表结点定义如下:

struct ListNode {
    int data;
    ListNode *next;
};

函数接口定义:

struct ListNode *readlist();
struct ListNode *deletem( struct ListNode *L, int m );

函数readlist从标准输入读入一系列正整数,按照读入顺序建立单链表。当读到−1时表示输入结束,函数应返回指向单链表头结点的指针。
函数deletem将单链表L中所有存储了m的结点删除。返回指向结果链表头结点的指针。

裁判测试程序样例:

#include <stdio.h>#include <stdlib.h>
struct ListNode {
    int data;
    struct ListNode *next;
};
struct ListNode *readlist();struct ListNode *deletem( struct ListNode *L, int m );void printlist( struct ListNode *L ){
     struct ListNode *p = L;
     while (p) {
           printf("%d ", p->data);
           p = p->next;
     }
     printf("\\n");
}
int main(){
    int m;
    struct ListNode *L = readlist();
    scanf("%d", &m);
    L = deletem(L, m);
    printlist(L);

    return 0;
}
/* 你的代码将被嵌在这里 */

输入样例:

10 11 10 12 10 -1
10

输出样例:

11 12

struct ListNode *readlist(){
    int number;
    scanf("%d",&number);
    struct ListNode *p,*head=NULL,*tail=head;//head要等于NULL
    while(number!=-1){
        p=(struct ListNode *)malloc(sizeof(struct ListNode ));
        p->data=number;
        if(head==NULL) head=p;
        else tail->next=p;
        tail=p;
        tail->next=NULL;//别忘了这一句!!
        scanf("%d",&number);//别忘了取地址!
    }
    return head;
}

struct ListNode *deletem( struct ListNode *L, int m ){//L就相当于head。
	struct ListNode *p,*tail;
    while(L&&L->data==m){
        p=L;
        L=L->next;
        free(p);
    }
    if(L==NULL) return NULL;
    p=L;
    tail=L->next;
    while(tail!=NULL){
        if(tail->data==m){//是tail->data不是tail
            p->next=tail->next;
            free(tail);
        }else p=tail;//在后面的p要前进一节。
        tail=p->next;//如果data连续为m的话,tail->next给p->next之后tail被free掉了(tail->next不存在了),所以要用p->next;!
    }
    return L;
}

LeetCode 905. 按奇偶排序数组

给定一个非负整数数组 A,返回一个数组,在该数组中, A 的所有偶数元素之后跟着所有奇数元素。
你可以返回满足此条件的任何数组作为答案。

示例:

输入:[3,1,2,4]
输出:[2,4,3,1]
输出 [4,2,3,1],[2,4,1,3] 和 [4,2,1,3] 也会被接受。

提示:

1.1 <= A.length <= 5000
2.0 <= A[i] <= 5000

int* sortArrayByParity(int* A, int ASize, int* returnSize){
    int *ret=(int *)malloc(sizeof(int)*ASize);
    int head=0,tail=ASize-1;
    *returnSize = ASize;
    for(int i=0;i<ASize;i++){
        if(A[i]&1) ret[tail--]=A[i];//==if(A[i] %2==1)
        else ret[head++]=A[i];
    }
    return ret;
}

PTA 习题1.8 二分查找 (20 分)

本题要求实现二分查找算法。

函数接口定义:

Position BinarySearch( List L, ElementType X );

其中List结构定义如下:

typedef int Position;typedef struct LNode *List;struct LNode {
    ElementType Data[MAXSIZE];
    Position Last; /* 保存线性表中最后一个元素的位置 */
};

L是用户传入的一个线性表,其中ElementType元素可以通过>、==、<进行比较,并且题目保证传入的数据是递增有序的。函数BinarySearch要查找X在Data中的位置,即数组下标(注意:元素从下标1开始存储)。找到则返回下标,否则返回一个特殊的失败标记NotFound。
裁判测试程序样例:

#include <stdio.h>#include <stdlib.h>
#define MAXSIZE 10
#define NotFound 0
typedef int ElementType;
typedef int Position;
typedef struct LNode *List;
struct LNode {
    ElementType Data[MAXSIZE];
    Position Last; /* 保存线性表中最后一个元素的位置 */
};
List ReadInput(); /* 裁判实现,细节不表。元素从下标1开始存储 */Position BinarySearch( List L, ElementType X );
int main(){
    List L;
    ElementType X;
    Position P;

    L = ReadInput();
    scanf("%d", &X);
    P = BinarySearch( L, X );
    printf("%d\\n", P);

    return 0;
}
/* 你的代码将被嵌在这里 */

输入样例1:

5
12 31 55 89 101
31

输出样例1:

2

输入样例2:

326 78 23331

输出样例2:

0

Position BinarySearch( List L, ElementType X )
{
    int low=1,high=L->Last,mid;
    while(low<=high){
        mid=(high+low)/2;
        if(L->Data[mid]>X) high-=1;
        else if(L->Data[mid]<X) low+=1;
        else return mid;
    }
    return NotFound;
}

PTA 实验11-2-6 奇数值结点链表 (20 分)

本题要求实现两个函数,分别将读入的数据存储为单链表、将链表中奇数值的结点重新组成一个新的链表。链表结点定义如下:

struct ListNode {
    int data;
    ListNode *next;
};

函数接口定义:

struct ListNode *readlist();
struct ListNode *getodd( struct ListNode **L );

函数readlist从标准输入读入一系列正整数,按照读入顺序建立单链表。当读到−1时表示输入结束,函数应返回指向单链表头结点的指针。
函数getodd将单链表L中奇数值的结点分离出来,重新组成一个新的链表。返回指向新链表头结点的指针,同时将L中存储的地址改为删除了奇数值结点后的链表的头结点地址(所以要传入L的指针)。

裁判测试程序样例:

#include <stdio.h>
#include <stdlib.h>
struct ListNode {
    int data;
    struct ListNode *next;
};
struct ListNode *readlist();struct ListNode *getodd( struct ListNode **L );void printlist( struct ListNode *L ){
     struct ListNode *p = L;
     while (p) {
           printf("%d ", p->data);
           p = p->next;
     }
     printf("\\n");
}
int main(){
    struct ListNode *L, *Odd;
    L = readlist();
    Odd = getodd(&L);
    printlist(Odd);
    printlist(L);

    return 0;
}
/* 你的代码将被嵌在这里 */

输入样例:

1 2 2 3 4 5 6 7 -1

输出样例:

1 3 5 7
2 2 4 6

struct ListNode *readlist(){
    int number;
    scanf("%d",&number);
    struct ListNode *p,*head,*tail=head=NULL;
    while(number!=-1){
        p=(struct ListNode*)malloc(sizeof(struct ListNode));
        p->data=number;
         p->next=NULL;//tail之后为NULL
        if(head==NULL) head=p;
        else tail->next=p;
        tail=p;
        scanf("%d",&number);
    }
    return head;
}
struct ListNode *getodd( struct ListNode **L ){
	struct ListNode *newhead,*p,*newtail=newhead=NULL,*head,*tail=head=NULL;;
	//int count=0;
	while(*L){
		p=(*L)->next;  //p为第二个结点,if和else中会修改*L->next因此提前写出来
		if((*L)->data%2!=0){
			if(newhead==NULL){
				newhead=*L;
			}else{
				newtail->next=*L;
			}
            newtail=*L;
			newtail->next=NULL;
            *L=p;//下一个结点
		}else{
			if(head==NULL){
				head=*L;
			}else{
				tail->next=*L;
			}
            tail=*L;
			tail->next=NULL;
			*L=p;
		}
	}
	*L=head;//最后把head还给*L,剩下的全是偶数
	return newhead;
}

PTA 实验11-2-7 统计专业人数 (15 分)

本题要求实现一个函数,统计学生学号链表中专业为计算机的学生人数。链表结点定义如下:

struct ListNode {
    char code[8];
    struct ListNode *next;
};

这里学生的学号共7位数字,其中第2、3位是专业编号。计算机专业的编号为02。

函数接口定义:

int countcs( struct ListNode *head );

其中head是用户传入的学生学号链表的头指针;函数countcs统计并返回head链表中专业为计算机的学生人数。

裁判测试程序样例:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct ListNode {
    char code[8];
    struct ListNode *next;
};
struct ListNode *createlist(); /*裁判实现,细节不表*/int countcs( struct ListNode *head );
int main(){
    struct ListNode  *head;

    head = createlist();
    printf("%d\\n", countcs(head));

    return 0;
}
/* 你的代码将被嵌在这里 */

输入样例:

1021202
2022310
8102134
1030912
3110203
4021205

输出样例:

3

int countcs(struct ListNode *head )
{
    struct ListNode *p;
    int count = 0;
    for(p = head; p != NULL; p = p->next)
        if(p->code[1] == '0' && p->code[2] == '2')
            count++;
    return count;
}

707. 设计链表

设计链表的实现。您可以选择使用单链表或双链表。单链表中的节点应该具有两个属性:valnextval 是当前节点的值,next 是指向下一个节点的指针/引用。如果要使用双向链表,则还需要一个属性 prev 以指示链表中的上一个节点。假设链表中的所有节点都是 0-index 的。
在链表类中实现这些功能:
get(index):获取链表中第 index 个节点的值。如果索引无效,则返回-1。
addAtHead(val):在链表的第一个元素之前添加一个值为 val 的节点。插入后,新节点将成为链表的第一个节点。
addAtTail(val):将值为 val 的节点追加到链表的最后一个元素。
addAtIndex(index,val):在链表中的第 index 个节点之前添加值为 val 的节点。如果 index 等于链表的长度,则该节点将附加到链表的末尾。如果 index 大于链表长度,则不会插入节点。如果index小于0,则在头部插入节点。
deleteAtIndex(index):如果索引 index 有效,则删除链表中的第 index 个节点。

示例:

MyLinkedList linkedList = new MyLinkedList();
linkedList.addAtHead(1);
linkedList.addAtTail(3);
linkedList.addAtIndex(1,2);   //链表变为1-> 2-> 3
linkedList.get(1);            //返回2
linkedList.deleteAtIndex(1);  //现在链表是1-> 3
linkedList.get(1);            //返回3

提示:

所有val值都在 [1, 1000] 之内。
操作次数将在  [1, 1000] 之内。
请不要使用内置的 LinkedList 库。

typedef struct {
    int val;
    struct MyLinkedList *next;
} MyLinkedList;

/** Initialize your data structure here. */
/*第一版,错误示范
思路:
创建一个obj,为NULL:
当有add的时候,判断如果现在obj是空的,就把它赋值成第一个节点。
再来一个,挂在这个节点的next上。

产生的问题:
1. obj本身指向的内容会随着第一个节点去改变。
   由于我们有接口可以在链表头上增加节点,这样的话,每次obj作为链表的第一个节点,它的指向都会变。
   感觉上没有什么问题,但实际上,在实测中obj从函数调用出来后会失效,(暂时还不知道为什么,求评论区指教,地址都是malloc的)
   导致错误。
2. 涉及index时,需要每次判断是否是空链表,对index = 0的情况也不好判断
3. 释放内存也带来问题

作者:songshushu
链接:<https://leetcode-cn.com/problems/design-linked-list/solution/707-she-ji-lian-biao-cyu-yan-chao-xiang-xi-ban-ben/>
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。*/
MyLinkedList* myLinkedListCreate() {
    MyLinkedList *obj=(MyLinkedList *)malloc(sizeof(MyLinkedList));
    obj->val=0;
    obj->next=NULL;
    return obj;
}

/** Get the value of the index-th node in the linked list. If the index is invalid, return -1. */
int myLinkedListGet(MyLinkedList* obj, int index) {
    /*  1,对明显的索引无效情况进行拦截
        三种索引无效情况
        1. index < 0
        2. 链表是空的,任何索引都无效。
        3. index超过了链表的长度*/
    if(index<0||!obj->next) return -1;
    MyLinkedList *p=obj->next;//要令p为第一个结点就是obj->next而不是obj
    for(int i=0;i<index;i++){//为什么i从0开始?难道结点也是从0开始数吗?
        p=p->next;
        if(!p){
            return -1;
        }
    }
    if(p) return p->val;
    else return -1;
    /*如果存在p就返回p的值,不存在的话需要返回-1;*/
}

/** Add a node of value val before the first element of the linked list. After the insertion, the new node will be the first node of the linked list. */
void myLinkedListAddAtHead(MyLinkedList* obj, int val) {
    MyLinkedList *p=(MyLinkedList*)malloc(sizeof(MyLinkedList));
    p->val=val;
    p->next=obj->next;
    obj->next=p;
}

/** Append a node of value val to the last element of the linked list. */
void myLinkedListAddAtTail(MyLinkedList* obj, int val) {//
    MyLinkedList *p=obj,*p1=(MyLinkedList *)malloc(sizeof(MyLinkedList));
    p1->val=val;
    p1->next=NULL;
    while(p->next){
        p=p->next;
    }
    p->next=p1;
}

/** Add a node of value val before the index-th node in the linked list. If index equals to the length of linked list, the node will be appended to the end of linked list. If index is greater than the length, the node will not be inserted. */
void myLinkedListAddAtIndex(MyLinkedList* obj, int index, int val) {
    if(index<=0) return myLinkedListAddAtHead(obj,val);/*如果是负索引直接头插法然后返回头结点就行
    改了半天原来是没有加return!!!!!!!returnreturn返回头结点后插入一个结点的链表;*/
    /*先在第一步完成初始化结点,再进行二三步*/
    MyLinkedList *p=obj,*p1=(MyLinkedList*)malloc(sizeof(MyLinkedList));
    p1->val=val;
    p1->next=NULL;
    /*找到第index-1个结点*/
    for(int i=0;i<index;i++){
        p=p->next;
        if(!p) free(p1);
    }
    p1->next=p->next;
    p->next=p1;
}
/** Delete the index-th node in the linked list, if the index is valid. */
void myLinkedListDeleteAtIndex(MyLinkedList* obj, int index) {
    /*删除用for好容易错*/
    MyLinkedList *p=obj,*p1;
    int j=0;
    while((p->next)&&(j<index)){
        j++;
        p=p->next;
    }
    p1=p->next;
    if(p1){
        p->next=p1->next;
        free(p1);
    }
}

void myLinkedListFree(MyLinkedList* obj) {
    MyLinkedList *p=obj->next;
    while(obj){
        p=obj;
        obj=obj->next;
        free(p);
    }
}

/**
 * Your MyLinkedList struct will be instantiated and called as such:
 * MyLinkedList* obj = myLinkedListCreate();
 * int param_1 = myLinkedListGet(obj, index);

 * myLinkedListAddAtHead(obj, val);

 * myLinkedListAddAtTail(obj, val);

 * myLinkedListAddAtIndex(obj, index, val);

 * myLinkedListDeleteAtIndex(obj, index);

 * myLinkedListFree(obj);
*/

141. 环形链表

给定一个链表,判断链表中是否有环。
如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。
如果链表中存在环,则返回 true 。 否则,返回 false

进阶:

你能用 O(1)(即,常量)内存解决此问题吗?

示例 1:

https://www.icode9.com/i/ll/?i=20210404185425155.png#pic_center

输入:head = [3,2,0,-4], pos = 1
输出:true
解释:链表中有一个环,其尾部连接到第二个节点。

示例 2:

https://www.icode9.com/i/ll/?i=20210404185434807.png#pic_center

输入:head = [1,2], pos = 0
输出:true
解释:链表中有一个环,其尾部连接到第一个节点。

示例 3:

https://www.icode9.com/i/ll/?i=20210404185442343.png#pic_center

输入:head = [1], pos = -1
输出:false
解释:链表中没有环。

提示:

链表中节点的数目范围是 [0, 104]
-105 <= Node.val <= 105
pos 为 -1 或者链表中的一个 有效索引 。

bool hasCycle(struct ListNode *head) {
    if(!head||!head->next) return false;
    struct ListNode *p1, *p2=p1=head;
    while(p2&&p2->next){//p2必须写前面不能写成while(p2->next&&p2)
        /*p2->next不存在的话说明不是循环链表,不是循环链表循环就会终止,然后执行最后的return false*/
        p1=p1->next;
        p2=p2->next->next;//p2每次比p1多走一步才能逐渐追上p1
        if(p1==p2) return true;
    }
    return false;
}

循环链表,先分别定义p1p2为慢快指针,令快指针p2每次比p1多走一步,逐渐追上p1,然后判断两个指针相等时返回true。 用while(p2&&p2->next)其中p2必须写前面不能写成while(p2->next&&p2)否则编译不通过,循环条件p2->next不存在的话说明不是循环链表,不是循环链表循环就会终止,然后执行最后的return false

LeetCode 142. 环形链表 II

给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。
为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。注意,pos 仅仅是用于标识环的情况,并不会作为参数传递到函数中。

说明:不允许修改给定的链表。

进阶:

你是否可以使用 O(1) 空间解决此题?

示例 1:

https://www.icode9.com/i/ll/?i=20210404190621230.png#pic_center

输入:head = [3,2,0,-4], pos = 1
输出:返回索引为 1 的链表节点解释:链表中有一个环,其尾部连接到第二个节点。

示例 2:

https://www.icode9.com/i/ll/?i=20210404190642668.png#pic_center

输入:head = [1,2], pos = 0
输出:返回索引为 0 的链表节点解释:链表中有一个环,其尾部连接到第一个节点。

示例 3:

https://www.icode9.com/i/ll/?i=20210404190650909.png#pic_center

输入:head = [1], pos = -1
输出:返回 null解释:链表中没有环。

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
struct ListNode *detectCycle(struct ListNode *head) {
    struct ListNode *p1,*p2=p1=head;
    int flag=0;//一定记得初始化为0啊
    while(p2&&p2->next){
        p1=p1->next;
        p2=p2->next->next;
        if(p1==p2) {
            flag=1;/*p1,p2相遇,flag存在的话一定有环*/
            break;
        }/*记得找到相遇点的话退出,如果不是循环链表不满足while条件自动退出*/
    }
    if(flag){
        p1=head;
        while(p1!=p2){
            p1=p1->next;
            p2=p2->next;
        }/*flag存在的话一定有环,循环一定能结束,结束后直接返回指针所指结点就行*/
        return p1;
    }
    return NULL;
}

双指针法,设快指针走了n圈时相遇,此时慢指针走了x+y个结点,通过计算得出环外长度x与相遇点到入环点长度z相等,快慢指针相遇后令其中一指针返回头结点,另一指针从相遇点继续出发,此时快慢指针同时移动相同距离,再次相遇后的结点即为入环结点。其中flag要记得初始化为0,p1,p2相遇,则

flag

存在,一定有环,用if判断

flag

存在的话令慢指针返回头结点再用

while

找到相遇的入环结点,因为

flag

存在环一定存在所以不必担心不必担心循环不会终止,终止后直接返回相遇结点。如果环不存在

flag=0

直接执行最后一步return NULL

https://www.icode9.com/i/ll/?i=20210404190413178.jpg?,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzUzNzQ5MjY2,size_16,color_FFFFFF,t_70#pic_center

LeetCode 160. 相交链表

编写一个程序,找到两个单链表相交的起始节点。
如下面的两个链表:

https://www.icode9.com/i/ll/?i=20210404191524617.png?,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzUzNzQ5MjY2,size_16,color_FFFFFF,t_70#pic_center

在节点 c1 开始相交。

示例 1:

https://www.icode9.com/i/ll/?i=20210404191535440.png?,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzUzNzQ5MjY2,size_16,color_FFFFFF,t_70#pic_center

输入:intersectVal = 8, listA = [4,1,8,4,5], listB = [5,0,1,8,4,5], skipA = 2, skipB = 3
输出:Reference of the node with value = 8
输入解释:相交节点的值为 8 (注意,如果两个链表相交则不能为 0)。从各自的表头开始算起,链表 A 为 [4,1,8,4,5],链表 B 为 [5,0,1,8,4,5]。在 A 中,相交节点前有 2 个节点;在 B 中,相交节点前有 3 个节点。

示例 2:

https://www.icode9.com/i/ll/?i=20210404191543235.png?,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzUzNzQ5MjY2,size_16,color_FFFFFF,t_70#pic_center

输入:intersectVal = 2, listA = [0,9,1,2,4], listB = [3,2,4], skipA = 3, skipB = 1
输出:Reference of the node with value = 2
输入解释:相交节点的值为 2 (注意,如果两个链表相交则不能为 0)。从各自的表头开始算起,链表 A 为 [0,9,1,2,4],链表 B 为 [3,2,4]。在 A 中,相交节点前有 3 个节点;在 B 中,相交节点前有 1 个节点。

示例 3:

https://www.icode9.com/i/ll/?i=20210404191550121.png?,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzUzNzQ5MjY2,size_16,color_FFFFFF,t_70#pic_center

输入:intersectVal = 0, listA = [2,6,4], listB = [1,5], skipA = 3, skipB = 2
输出:null
输入解释:从各自的表头开始算起,链表 A 为 [2,6,4],链表 B 为 [1,5]。由于这两个链表不相交,所以 intersectVal 必须为 0,而 skipA 和 skipB 可以是任意值。解释:这两个链表不相交,因此返回 null。

注意:

如果两个链表没有交点,返回 null.
在返回结果后,两个链表仍须保持原有的结构。
可假定整个链表结构中没有循环。
程序尽量满足 O(n) 时间复杂度,且仅用 O(1) 内存。

struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
    if(!headA||!headB) return NULL;
    struct ListNode *p1=headA,*p2=headB;
    while(p1!=p2){
        p1=p1?p1->next:headB;
        p2=p2?p2->next:headA;
        /*把NULL也同时看做两个链表的最后一个结点,对分别的长度与总长度都没有影响。
        写p1p2 instead of p1->next p2->next 还可以判断空链表的情况*/
    }
    return p1;
}

数学证明,他们每一次轮回的路程相等,都为A+B=B+A。
如果不相交,他们将在走过相同的结点数后同时走到最后的NULL,循环结束。
如果相交,那么我们逆推,既然能在尾节点相遇,那么尾节点的前继节点也是相遇,直到我们逆推到第一个相交点。

LeeCode 19. 删除链表的倒数第 N 个结点

给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。

进阶:你能尝试使用一趟扫描实现吗?

示例 1:

https://www.icode9.com/i/ll/?i=20210404192100863.jpg?,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzUzNzQ5MjY2,size_16,color_FFFFFF,t_70#pic_center

输入:head = [1,2,3,4,5], n = 2输出:[1,2,3,5]

示例 2:

输入:head = [1], n = 1输出:[]

示例 3:

输入:head = [1,2], n = 1输出:[1]

提示:

链表中结点的数目为 sz
1 <= sz <= 30
0 <= Node.val <= 100
1 <= n <= sz

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */

struct ListNode* removeNthFromEnd(struct ListNode* head, int n){
    struct ListNode*p=NULL,*p1,*p2=p1=head;
    int k=n;
    while(k-1){
        p2=p2->next;
        k--;
    }/*使p2前进n-1个结点到达第n个结点,等价于for(int i=0;i<n-1;i++) p2=p2->next;*/
    while(p2->next){
        p2=p2->next;
        p=p1;
        p1=p1->next;
    }
    if(p==NULL) head=head->next;/*处理边界值很重要,例如k<0时删除头结点*/
    else p->next=p1->next;
    free(p1);
    return head;
}

LeeCode 206. 反转链表

反转一个单链表。

示例:

输入: 1->2->3->4->5->NULL输出: 5->4->3->2->1->NULL

进阶:

你可以迭代或递归地反转链表。你能否用两种方法解决这道题?

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */

//**方法一:迭代**//
struct ListNode* reverseList(struct ListNode* head){
    struct ListNode*cur=head,*pre=NULL;
    while(cur){
        struct ListNode*tempnext=cur->next; /*若令temp=cur,temp->next会随着cur->next改变而改变,因此需要提前存起来的是cur->next而不是cur*/
        cur->next=pre;
        pre=cur;/*pre一定要紧跟cur这样才能令前一结点指向后一个*/
        cur=tempnext;
    }
    return pre;/*若是头结点cur不存在则直接返回NULL*/
}

//**方法二:递归**//
struct ListNode* reverseList(struct ListNode* head){
    if(!head||!head->next) return head;
    struct ListNode*newhead=reverseList(head->next);
    head->next->next=head;
    head->next=NULL;
    return newhead;
 }

从后开始往前递归,递归到最后,最后一个结点是newhead,倒数第二个结点是head,使newhead指向head然后取消head->next的指向newhead,一层一层从后往前递归过程中,改变的是head->next->next和head->next,而newhead一直是最后一个结点没有变!链表变为由最后一项开始往前指,原先的头结点指向NULL。因此返回最后新的头结点

https://www.icode9.com/i/ll/?i=20210404194216455.jpg?,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzUzNzQ5MjY2,size_16,color_FFFFFF,t_70#pic_center

https://www.icode9.com/i/ll/?i=20210404194216474.jpg?,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzUzNzQ5MjY2,size_16,color_FFFFFF,t_70#pic_center

https://www.icode9.com/i/ll/?i=20210404194216361.jpg?,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzUzNzQ5MjY2,size_16,color_FFFFFF,t_70#pic_center

https://www.icode9.com/i/ll/?i=20210404194216395.jpg?,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzUzNzQ5MjY2,size_16,color_FFFFFF,t_70#pic_center

LeeCode 328. 奇偶链表

给定一个单链表,把所有的奇数节点和偶数节点分别排在一起。请注意,这里的奇数节点和偶数节点指的是节点编号的奇偶性,而不是节点的值的奇偶性。
请尝试使用原地算法完成。你的算法的空间复杂度应为 O(1),时间复杂度应为 O(nodes),nodes 为节点总数。

示例 1:

输入: 1->2->3->4->5->NULL
输出: 1->3->5->2->4->NULL

示例 2:

输入: 2->1->3->5->6->4->7->NULL
输出: 2->3->6->7->1->5->4->NULL

说明:

应当保持奇数节点和偶数节点的相对顺序。
链表的第一个节点视为奇数节点,第二个节点视为偶数节点,以此类推。

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 判断整个链表是否遍历完,例如 1->2->3->4->5->6->NULL,当遍历到节点值为 6 的节点的时候(pEvenHead->next == NULL),代表整个链表遍历完了,1->2->3->4->5->NULL,当遍历到节点值为 5 的节点的时候(oddHead->next == NULL),代表整个链表遍历完了。官方的判断条件 while (even != null && even.next != null) 其实也是一样的,它的 even 就是 odd->next 。*/

struct ListNode* oddEvenList(struct ListNode* head){
    if(!head||!head->next) return head;
    struct ListNode*oddhead=head,*evenhead=head->next,*pevenhead=evenhead;
    while(oddhead->next&&pevenhead->next){
        oddhead->next=oddhead->next->next;
        oddhead=oddhead->next;
        pevenhead->next=pevenhead->next->next;
        pevenhead=pevenhead->next;
    }
    oddhead->next=evenhead;
    return head;
}

先定义oddhead用来存储奇数结点,pevenhead存储偶数结点,evenhead固定为偶数结点的头结点,用while循环遍历整个链表,当oddhead->next或pevenhead->next其中任一不存在时表明链表完成遍历,表示为while(oddhead->next&&pevenhead->next)此时令最后一个奇数结点指向固定好的evenhead,返回头结点head即可。

LeetCode 21. 合并两个有序链表

将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。

示例 1:

https://www.icode9.com/i/ll/?i=20210406223339320.png?,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzUzNzQ5MjY2,size_16,color_FFFFFF,t_70#pic_center

输入:l1 = [1,2,4], l2 = [1,3,4]输出:[1,1,2,3,4,4]

示例 2:

输入:l1 = [], l2 = []输出:[]

示例 3:

输入:l1 = [], l2 = [0]输出:[0]

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
/*法一:递归*/
struct ListNode* mergeTwoLists(struct ListNode* l1, struct ListNode* l2){
    if(l1==NULL) return l2;
    if(l2==NULL) return l1;
    if(l1->val<l2->val) {
        l1->next=mergeTwoLists(l1->next,l2);
        return l1;
    }else {
        l2->next=mergeTwoLists(l2->next,l1);
        return l2;
    }
    /*每一次遍历将较小结点->next和另一链表中结点更小的结点赋给结点的next,直至遍历为空,结束遍历*/
}

/*方法二:迭代*/
struct ListNode* mergeTwoLists(struct ListNode* l1, struct ListNode* l2){
    struct ListNode*head=(struct ListNode*)malloc(sizeof(struct ListNode)),*p=head;
    /*控制head不变,双指针p做小尾巴来连接结点*/
    if(!l1) return l2;
    if(!l2) return l1;
    while(l1&&l2){
        if(l1->val<=l2->val){//l1->val==l2->val的话就直接按顺序存在p之后。
            p->next=l1;
            l1=l1->next;
        }else{
            p->next=l2;
            l2=l2->next;
        }
        p=p->next;
    }
    if(!l1) p->next=l2;
    if(!l2) p->next=l1;
    return head->next;
}
/*方法三:硬拉+简化版冒泡*/
struct ListNode* mergeTwoLists(struct ListNode* l1, struct ListNode* l2){
    if(!l1) return l2;
    if(!l2) return l1;
    struct ListNode*p=l1,*q=NULL;
    while(p->next){
        p=p->next;
    }
    p->next=l2;
    for(p=l1;p;p=p->next){
        for(q=p->next;q;q=q->next){
            if(p->val>q->val){
                int t=p->val;
                p->val=q->val;
                q->val=t;
            }
        }
    }
    return l1;
}

上次用的是把两个链表连接后再简化版冒泡排序排好,这次用递归和迭代方法一递归,由于每一层递归返回值小的结点并且给值小的结点连接下一个小的结点,当l1或l2中任意为空时递归结束,第一层递归返回l1和l2中更小的头结点,相当于直接返回一个排好序的链表。方法二迭代,定义两个指针,head不变用于最后返回,p当作小尾巴来连接新加入的结点,当l1l2还存在时依次插入之后的结点,不存在时直接将剩余的一条链表连接在后面因为l1l2已经升序排列了,然后返回头结点。其中if(l1->val<=l2->val)小于号后面要加等于,不加的话虽然能通过LEETCODE但过不了PTA的一个测试点。

LeetCode 203. 移除链表元素

给你一个链表的头节点 head 和一个整数 val ,请你删除链表中所有满足 Node.val == val 的节点,并返回 新的头节点 。

示例 1:

输入:head = [1,2,6,3,4,5,6], val = 6输出:[1,2,3,4,5]

示例 2:

输入:head = [], val = 1输出:[]

示例 3:

输入:head = [7,7,7,7], val = 7输出:[]

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */

struct ListNode* removeElements(struct ListNode* head, int val){
    while(head){
        if(head->val==val) head=head->next;
        else break;
    }
    if(!head ) return NULL;
    struct ListNode*p2=head->next,*p1=head;
    while(p2){
        if(p2->val==val){//要删除p2的话就只动p2,只改变p1的next就行
            p1->next=p2->next;
            free(p2);
            p2=p1->next;
        }else {//不删除的话p1p2一起前进
            p1=p1->next;//p1要比p2先前进再领p2=p1->next
            p2=p1->next;
        }
    }
    return head;
}

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode removeElements(ListNode head, int val) {
        ListNode dummyhead = new ListNode(0),temp = dummyhead;
        dummyhead.next=head;
        while(temp.next != null){
            if(temp.next.val==val){
                temp.next = temp.next.next;
            }else{
                temp = temp.next;
            }
        }
        return dummyhead.next;
    }
}

LeetCode 61. 旋转链表

给你一个链表的头节点 head ,旋转链表,将链表每个节点向右移动 k 个位置。

示例 1:

https://www.icode9.com/i/ll/?i=img_convert/192699c8d11d5f13a4f06fdf4823fd2e.png

输入:head = [1,2,3,4,5], k = 2
输出:[4,5,1,2,3]

示例 2:

https://www.icode9.com/i/ll/?i=img_convert/98af10b6c9f0f827ddb34c07b83e40c6.png

输入:head = [0,1,2], k = 4
输出:[2,0,1]

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
/*考虑不太周全,1.没考虑k值过大的问题,要继续努力
            2.没考虑头结点为空
            3.没考虑k为count的倍数*/
struct ListNode* rotateRight(struct ListNode* head, int k){
    if(!head)  return NULL;
    struct ListNode*p=head,*p1=NULL,*p2=NULL;
    int count=0,m=0;
    while(p){
        p=p->next;
        count++;
    }
    k%=count;
    if(k==0) return head;//是i的倍数或为0的话直接返回头结点
    p=head;
    p1=head;
    while(count-k-m-1){
        p=p->next;
        m++;
    }/*p走到倒数第k+1个,p1走到倒数第k个*/
    p1=p->next;//这句别忘啊
    p->next=NULL;
    p2=p1;
    while(p2->next) p2=p2->next;
    p2->next=head;
    return p1;
}

LeetCode 2. 两数相加

给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。

请你将两个数相加,并以相同形式返回一个表示和的链表。

你可以假设除了数字 0 之外,这两个数都不会以 0 开头。

示例 1:

https://www.icode9.com/i/ll/?i=img_convert/7d87baa243f73bac7930b19529e847c7.png

输入:l1 = [2,4,3], l2 = [5,6,4]
输出:[7,0,8]
解释:342 + 465 = 807.

示例 2:

输入:l1 = [0], l2 = [0]
输出:[0]

示例 3:

输入:l1 = [9,9,9,9,9,9,9], l2 = [9,9,9,9]
输出:[8,9,9,9,0,0,0,1]

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
 /*1.没有考虑到当l1,l2结束时tempval还存在的话需要在后面进一位。
 2.带头结点的,没有给新的结点申请空间。先申请新的结点赋值,比先赋值新的结点再连接要简单。使用带头结点的,先申请一个结点再对新建结点进行赋值,下一次循环进行时申请新的结点,如果不带头结点的话用先申请后赋值的方法会多在循环最后多申请一个结点。
 坚持自己正确的想法*/
struct ListNode* addTwoNumbers(struct ListNode* l1, struct ListNode* l2){
    if(!l1) return l2;
    if(!l2) return l1;
    struct ListNode*returnlist=(struct ListNode*)malloc(sizeof(struct ListNode)),*p=returnlist;
    int tempval=0;
    while(l1||l2||tempval){
        if(l1){
            tempval+=l1->val;
            l1=l1->next;
        }
        if(l2){
            tempval+=l2->val;
            l2=l2->next;
        }
    p->next=(struct ListNode*)malloc(sizeof(struct ListNode));
    p=p->next;
    p->val=tempval%10;
    tempval/=10;
    }
    p->next=NULL;
    return returnlist->next;
}

LeetCode 138. 复制带随机指针的链表

给你一个长度为 n 的链表,每个节点包含一个额外增加的随机指针 random ,该指针可以指向链表中的任何节点或空节点。

构造这个链表的 深拷贝。 深拷贝应该正好由 n全新 节点组成,其中每个新节点的值都设为其对应的原节点的值。新节点的 next 指针和 random 指针也都应指向复制链表中的新节点,并使原链表和复制链表中的这些指针能够表示相同的链表状态。复制链表中的指针都不应指向原链表中的节点

例如,如果原链表中有 XY 两个节点,其中 X.random --> Y 。那么在复制链表中对应的两个节点 xy ,同样有 x.random --> y

返回复制链表的头节点。

用一个由 n 个节点组成的链表来表示输入/输出中的链表。每个节点用一个 [val, random_index] 表示:

  • val:一个表示 Node.val 的整数。
  • random_index:随机指针指向的节点索引(范围从 0n-1);如果不指向任何节点,则为 null

你的代码 接受原链表的头节点 head 作为传入参数。

示例 1:

https://www.icode9.com/i/ll/?i=img_convert/f8f9507766d2b669c1fc4602abb42bcc.png

输入:head = [[7,null],[13,0],[11,4],[10,2],[1,0]]
输出:[[7,null],[13,0],[11,4],[10,2],[1,0]]

示例 2:

https://www.icode9.com/i/ll/?i=img_convert/5b1d9935e44c90100e9e651df9c95804.png

输入:head = [[1,1],[2,1]]
输出:[[1,1],[2,1]]

示例 3:

https://www.icode9.com/i/ll/?i=img_convert/644c55218eecea6200881f4bea3a3a95.png

输入:head = [[3,null],[3,0],[3,null]]
输出:[[3,null],[3,0],[3,null]]

示例 4:

输入:head = []
输出:[]
解释:给定的链表为空(空指针),因此返回 null。


/**
 * Definition for a Node.
 * struct Node {
 *     int val;
 *     struct Node *next;
 *     struct Node *random;
 * };
 */
/* 1.没有写head为空的情况
    2.深拷贝把while写成了if*/
/*法一:两次遍历暴力求解*/
struct Node* copyRandomList(struct Node* head)
{
    if(!head) return head;
    struct Node*p1=head,*chead=NULL,*p2=chead;
    struct Node*u1,*u2;
    /*浅拷贝*/
    while(p1)
    {/*建立一个新的尾巴结点然后令之前的尾巴指向这个结点*/
        struct Node* temp=(struct Node*)malloc(sizeof(struct Node));
        temp->val=p1->val;
        temp->next=NULL;
        temp->random=NULL;

        if(!chead) chead=temp;
        else p2->next=temp;
        p2=temp;
        p1=p1->next;
    }
    p1=head;
    p2=chead;
    /*深拷贝*/
    while(p1){
        if(!p1->random)
            p2->random=NULL;
        else
         {
            u1=head;
            u2=chead;
            while(p1->random!=u1){
                u1=u1->next;
                u2=u2->next;
            }
            p2->random=u2;
        }
        p1 = p1->next;
        p2 = p2->next;
    }
    return chead;
}

LeetCode 155. 最小栈

设计一个支持 pushpoptop 操作,并能在常数时间内检索到最小元素的栈。

  • push(x) —— 将元素 x 推入栈中。
  • pop() —— 删除栈顶的元素。
  • top() —— 获取栈顶元素。
  • getMin() —— 检索栈中的最小元素。

示例:

输入:
["MinStack","push","push","push","getMin","pop","top","getMin"]
[[],[-2],[0],[-3],[],[],[],[]]

输出:
[null,null,null,null,-3,null,0,-2]

解释:
MinStack minStack = new MinStack();
minStack.push(-2);
minStack.push(0);
minStack.push(-3);
minStack.getMin();   --> 返回 -3.
minStack.pop();
minStack.top();      --> 返回 0.
minStack.getMin();   --> 返回 -2.

/*1.栈压入结点的时候更新minval没有考虑到当obj为空(!obj->top)时的情况
  2.遍历寻找寻找最小值结点,遍历前要判断头结点是否存在!!存在的话在更新minval,不存在则不能对minval进行操作,否则会改变原本正确的最小值。
  3.入栈出栈也需要判断是否有头结点!!入栈出栈都是一次操作,用if判断一次是否有头结点然后进行操作就足够了。一定要先出栈再更新最小值呀!!
  4.有了更新最小值函数后在一个结点出栈后就可以直接调用更新最小值,不必再次手动更新最小值。
  5.返回最小值函数(int minStackGetMin)中,用if判断若obj存在直接返回最小值即可,记得若不存在返回-11!!因为别的函数逻辑正确。
  6.返回值为int类型的函数不要返回NULL,要返回-1。
  7.要先用if判断再push新结点,否则若原本没有头结点的话会影响obj->minval的赋值。
  8.写完头指针存在的情况后记得写头指针不存在的。
  9.free后要令指针为NULL*/
typedef struct node{
    int val;
    struct node *next;
}node;

typedef struct MinStack{
    node *top;
    int minval;
}MinStack;

MinStack* minStackCreate() {
    MinStack*p=(MinStack*)malloc(sizeof(MinStack));
    p->top=NULL;
    return p;
}

void minStackPush(MinStack* obj, int x) {
    if(!obj->top||(obj->top&&x<obj->minval)) obj->minval=x;

    node*temp=(node*)malloc(sizeof(node));
    temp->val=x;
    temp->next = obj->top;
    obj->top=temp;
}

void findMinVal(MinStack *obj)
//更新最小值的函数
{
    struct node*p=obj->top;
    if(p){
        obj->minval=p->val;
        while(p){
            if(obj->minval>p->val) obj->minval=p->val;
            p=p->next;
        }
    }
}

void minStackPop(MinStack* obj) {
    struct node*p=obj->top;
    if(p){
        obj->top=obj->top->next;//一定要先出栈再更新最小值呀!
        if(p->val==obj->minval) findMinVal(obj);
        free(p);
        p=NULL;
    }
}

int minStackTop(MinStack* obj) {
    if(obj->top) return obj->top->val;
    else return -1;
}

int minStackGetMin(MinStack* obj) {
    struct node*p=obj->top;
    if(p) return obj->minval;
    return -1;
    /*if(p){
        obj->minval=p->val;
        while(p){
            if(obj->minval>p->val) obj->minval=p->val;
            p=p->next;
        }
    }
    return obj->minval;*/
}

void minStackFree(MinStack* obj) {
    node*p=obj->top;
    while(p){
        node*p1=p->next;
        free(p);
        p=p1;
    }
    free (obj);
}

/**
 * Your MinStack struct will be instantiated and called as such:
 * MinStack* obj = minStackCreate();
 * minStackPush(obj, val);

 * minStackPop(obj);

 * int param_3 = minStackTop(obj);

 * int param_4 = minStackGetMin(obj);

 * minStackFree(obj);
*/

LeetCode 1021. 删除最外层的括号

有效括号字符串为空 ("")"(" + A + ")"A + B,其中 AB 都是有效的括号字符串,+ 代表字符串的连接。例如,"""()""(())()""(()(()))" 都是有效的括号字符串。

如果有效字符串 S 非空,且不存在将其拆分为 S = A+B 的方法,我们称其为原语(primitive),其中 AB 都是非空有效括号字符串。

给出一个非空有效字符串 S,考虑将其进行原语化分解,使得:S = P_1 + P_2 + ... + P_k,其中 P_i 是有效括号字符串原语。

S 进行原语化分解,删除分解中每个原语字符串的最外层括号,返回 S

示例 1:

输入:"(()())(())"
输出:"()()()"
解释:
输入字符串为 "(()())(())",原语化分解得到 "(()())" + "(())",
删除每个部分中的最外层括号后得到 "()()" + "()" = "()()()"。

示例 2:

输入:"(()())(())(()(()))"
输出:"()()()()(())"
解释:
输入字符串为 "(()())(())(()(()))",原语化分解得到 "(()())" + "(())" + "(()(()))",
删除每个部分中的最外层括号后得到 "()()" + "()" + "()(())" = "()()()()(())"。

示例 3:

输入:"()()"
输出:""
解释:
输入字符串为 "()()",原语化分解得到 "()" + "()",
删除每个部分中的最外层括号后得到 "" + "" = ""。

/*最外层第一个左括号入栈时count为0,不入栈,中间的括号count不为0会入栈,最外层最后一个右括号入栈时count先减为0,为0后不入栈,最后将‘\\0‘入栈表示字符结尾。
if(count!= 0)放在count++前面才能保证不记录第一个左括号,同理下面count先——使得count先变为0才能不记录最后一个右括号 */
char * removeOuterParentheses(char * S){
    int count=0,top=-1;
    char*stack=(char*)malloc((sizeof(char)*strlen(S)+1));
    for(int i=0;i<strlen(S);i++){
        if(S[i]=='('){
            if(count!=0)
            {
                stack[++top]=S[i];
            }
            count++;
        }
        if(S[i]==')')
        {
            count--;
            if(count!=0){
                stack[++top]=S[i];
            }
        }
    }
    stack[++top]='\\0';
    return stack;
}

LeetCode 剑指 Offer 09. 用两个栈实现队列

用两个栈实现一个队列。队列的声明如下,请实现它的两个函数 appendTaildeleteHead ,分别完成在队列尾部插入整数和在队列头部删除整数的功能。(若队列中没有元素,deleteHead 操作返回 -1 )

示例 1:

输入:
["CQueue","appendTail","deleteHead","deleteHead"]
[[],[3],[],[]]
输出:[null,null,3,-1]

示例 2:

输入:
["CQueue","deleteHead","appendTail","appendTail","deleteHead","deleteHead"]
[[],[],[5],[2],[],[]]
输出:[null,-1,null,null,5,2]

提示:

  • 1 <= values <= 10000
  • 最多会对 appendTail、deleteHead 进行 10000 次调用
/*1.定义结构时不需要赋值,列出元素就行,在创建函数中进行赋值,创建函数中len仍需表示为obj->len。
  2.在函数中的数组下标使用top时仍需写为obj->s[++obj->top],不能忽略了obj->
  3.删除时,top2下标用来删除,若top2为-1,证明删空了,就返回-1,没删空返回top2--,先返回      obj->s[top2--]后对top2--,所以不用担心top2为0。
    调用一次函数只删除一个结点
  4.元素出入栈时,入栈的先obj->s[++top],出栈的为obj->s[top--],这样可以保证第一个top出栈。
*/
typedef struct CQueue{
    int len;
    int *s1,top1;
    int *s2,top2;
} CQueue;

CQueue* cQueueCreate() {
    CQueue*p=(CQueue*)malloc(sizeof(CQueue));
    p->len=1000;
    p->s1=malloc(p->len*sizeof(int));
    p->s2=malloc(p->len*sizeof(int));
    p->top1=-1;
    p->top2=-1;

    return p;
}

void cQueueAppendTail(CQueue* obj, int value) {//栈1中进行
    while(obj->top2!=-1){
        obj->s1[++obj->top1]=obj->s2[obj->top2--];
    }
    obj->s1[++obj->top1]=value;
}

int cQueueDeleteHead(CQueue* obj) {//栈2中进行
    while(obj->top1!=-1){
        obj->s2[++obj->top2]=obj->s1[obj->top1--];
    }
    return obj->top2==-1?-1:obj->s2[obj->top2--];
}

void cQueueFree(CQueue* obj) {
    free(obj->s1);
    free(obj->s2);
    free(obj);
}

/**
 * Your CQueue struct will be instantiated and called as such:
 * CQueue* obj = cQueueCreate();
 * cQueueAppendTail(obj, value);

 * int param_2 = cQueueDeleteHead(obj);

 * cQueueFree(obj);
*/

LeetCode 622. 设计循环队列

设计你的循环队列实现。 循环队列是一种线性数据结构,其操作表现基于 FIFO(先进先出)原则并且队尾被连接在队首之后以形成一个循环。它也被称为“环形缓冲器”。

循环队列的一个好处是我们可以利用这个队列之前用过的空间。在一个普通队列里,一旦一个队列满了,我们就不能插入下一个元素,即使在队列前面仍有空间。但是使用循环队列,我们能使用这些空间去存储新的值。

你的实现应该支持如下操作:

MyCircularQueue(k): 构造器,设置队列长度为 k 。
Front: 从队首获取元素。如果队列为空,返回 -1 。
Rear: 获取队尾元素。如果队列为空,返回 -1 。
enQueue(value): 向循环队列插入一个元素。如果成功插入则返回真。
deQueue(): 从循环队列中删除一个元素。如果成功删除则返回真。
isEmpty(): 检查循环队列是否为空。
isFull(): 检查循环队列是否已满。

示例:

MyCircularQueue circularQueue = new MyCircularQueue(3); // 设置长度为 3
circularQueue.enQueue(1); // 返回 true
circularQueue.enQueue(2); // 返回 true
circularQueue.enQueue(3); // 返回 true
circularQueue.enQueue(4); // 返回 false,队列已满
circularQueue.Rear(); // 返回 3
circularQueue.isFull(); // 返回 true
circularQueue.deQueue(); // 返回 true
circularQueue.enQueue(4); // 返回 true
circularQueue.Rear(); // 返回 4

提示:

所有的值都在 0 至 1000 的范围内;
操作数将在 1 至 1000 的范围内;
请不要使用内置的队列库。

/*  1.循环队列obj->front==obj->rear&&obj->flag=0时为空。(obj->rear+1)%queuesize==front时为满。
    2.obj->rear那一格不存数据。
    3.数据用数据域指针*data来表示,使用时申请空间,记得申请完空间要转化为(int)。
    4.没有定义队列大小int size,没有定义int flag判断队列是否满。
    5.创建队列时没有进行参数检查。
    6.元素入队时要进行队列是否满的判断,出队时要进行队列是否空的判断。
    7.myCircularQueueFront和myCircularQueueRear只返回元素值,不对下标进行操作。myCircularQueueRear返回时若rear为0返回obj->val[obj->size-1],obj->val[obj->rear-1]。先判断队列是否为空。
    8.flag是否为0在入队出队和初始化中有了判断和赋值,myCircularQueueIsEmpty和myCircularQueueIsFull只需要判断flag的数值即可判断队列是否为满。
    */
typedef struct MyCircularQueue {
    int *val;						//保存元素的队列
    int front;
    int size;
    int rear;
    int flag;//标志队列是否满 ->   1 满   0 不满
            //如果不用此标志位的话,数组需要留多一位空位用来 判别 队列是否满
            //即:当 头指针 在 尾指针的下一个位置(多的空位)时,队列满。
} MyCircularQueue;

bool myCircularQueueIsEmpty(MyCircularQueue* obj);
bool myCircularQueueIsFull(MyCircularQueue* obj);

MyCircularQueue* myCircularQueueCreate(int k) {			//k为队列长度
    if(k<0) return NULL;

    MyCircularQueue *p=(MyCircularQueue*)malloc(sizeof(MyCircularQueue));
    p->val=(int*)malloc(k*sizeof(int));
    p->rear=p->front=0;
    p->size=k;
    p->flag=0;
    return p;
}

bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {//
    if(myCircularQueueIsFull(obj))
        return false;
    obj->val[obj->rear]=value;
    obj->rear=(obj->rear+1)%obj->size;
    if (obj->rear == obj->front)//在插入新元素后,两指针指向相同,则队列为满。
        obj->flag=1;
    return true;
}

bool myCircularQueueDeQueue(MyCircularQueue* obj) {//
    if(myCircularQueueIsEmpty(obj))
        return false;
    obj->val[obj->front]=0;//清除队头数据
    obj->front=(obj->front+1)%obj->size;//头指针后移
    obj->flag=0;
    return true;
}

int myCircularQueueFront(MyCircularQueue* obj) {
    if(myCircularQueueIsEmpty(obj))
        return -1;
    return obj->val[obj->front];
}

int myCircularQueueRear(MyCircularQueue* obj) {
    if(myCircularQueueIsEmpty(obj))
        return -1;
    if(obj->rear == 0)				//若队尾指针指向数组[0]则返回数组[obj->size-1]
        return obj->val[obj->size-1];
    else
        return obj->val[obj->rear-1];
}

bool myCircularQueueIsEmpty(MyCircularQueue* obj) {
    if(obj->front==obj->rear&&obj->flag==0)
        return true;
    return false;
}

bool myCircularQueueIsFull(MyCircularQueue* obj) {
    if(obj->flag==1)
        return true;
    return false;
}

void myCircularQueueFree(MyCircularQueue* obj) {
    free(obj->val);
    obj->val = NULL;
    free(obj);
    obj = NULL;
}

/**
 * Your MyCircularQueue struct will be instantiated and called as such:
 * MyCircularQueue* obj = myCircularQueueCreate(k);
 * bool param_1 = myCircularQueueEnQueue(obj, value);

 * bool param_2 = myCircularQueueDeQueue(obj);

 * int param_3 = myCircularQueueFront(obj);

 * int param_4 = myCircularQueueRear(obj);

 * bool param_5 = myCircularQueueIsEmpty(obj);

 * bool param_6 = myCircularQueueIsFull(obj);

 * myCircularQueueFree(obj);
*/

LeetCode 20. 有效的括号

给定一个只包括 '('')''{''}''['']' 的字符串 s ,判断字符串是否有效。

有效字符串需满足:

  1. 左括号必须用相同类型的右括号闭合。
  2. 左括号必须以正确的顺序闭合。

示例 1:

输入:s = "()"
输出:true

示例 2:

输入:s = "()[]{}"
输出:true

示例 3:

输入:s = "(]"
输出:false

示例 4:

输入:s = "([)]"
输出:false

示例 5:

输入:s = "{[]}"
输出:true

提示:

  • 1 <= s.length <= 104
  • s 仅由括号 '()[]{}' 组成

通过次数595,761

提交次数1,355,616

/*先判断 top是否等于0,如果等于0,那么用return 返回 true(值为1),否则,用return 返回 false (值为0)。
strlen仅仅计算字符个数,不包括最后的\\0。
*/
bool isValid(char * s){
    char*stack=(char*)malloc(10000*sizeof(char));
    if(strlen(s)&1) return false;
    int top=-1;
    for(int i=0;i<strlen(s);i++){
        if(s[i]=='(')
            stack[++top]=')';
        else if(s[i]=='[')
            stack[++top]=']';
        else if(s[i]=='{')
            stack[++top]='}';
        else if(top==-1||stack[top]!=s[i])
            return false;
        else top--;
    }
    return top==-1;
}

左括号与右括号对应,说明括号有效。遍历字符串,遇到左括号,则把对应右括号入栈,若是右括号,则判断栈顶是否为一样的右括号,不一样则不匹配,一样则出栈,继续遍历字符串下一个字符。最后若栈不为空则说明左括号数大于右括号,不匹配。

/*判断的最后两种情况也可写为
若是右括号,则判断栈顶是否为一样的右括号,不一样则不匹配,一样则出栈,*/
            else if(top > -1 && stack[top] == s[i])
            top--;
        else
            return false;

LeetCode 739. 每日温度

请根据每日 气温 列表,重新生成一个列表。对应位置的输出为:要想观测到更高的气温,至少需要等待的天数。如果气温在这之后都不会升高,请在该位置用 0 来代替。

例如,给定一个列表 temperatures = [73, 74, 75, 71, 69, 72, 76, 73],你的输出应该是 [1, 1, 4, 2, 1, 1, 0, 0]

提示:气温 列表长度的范围是 [1, 30000]。每个气温的值的均为华氏度,都是在 [30, 100] 范围内的整数。

/*法一:遍历+栈*/
/**
 * Note: The returned array must be malloced, assume caller calls free().
    1.使用calloc函数的话就不必初始化为再用malloc初始化为0,malloc就需要。因为calloc在动态分配完内存后,自动初始化该内存空间为零,而malloc不初始化,里边数据是随机的垃圾数据。malloc函数:函数返回值是一个对象。calloc函数:函数返回值是一个数组。
    2.当栈不为空且当前温度大于栈顶元素温度时,不但要给答案赋值,还要出栈!
    3.栈中存的是天数(位置),入栈时指针先加一,写为stack[++top] = i;
    4.stack[top]为栈顶元素的天数,因此T[stack[top]为栈顶元素温度。
 */

int* dailyTemperatures(int* T, int TSize, int* returnSize){
    int *res=(int*)malloc(sizeof(int)*TSize);
    memset(res,0,TSize*sizeof(int));
    int top=-1;
    int stack[TSize];

    for(int i=0;i<TSize;i++){
        while(top>-1&&T[i]>T[stack[top]]){
            res[stack[top]]= i - stack[top];//栈顶元素那一天
            top--;//一定要记得出栈
        }
        stack[++top] = i;		/*先将第一天入栈在判断第二天,所以要把while写在入栈的上边,不然第一天和自己开始比,最后结果全部为0*/
    }

    *returnSize=TSize;
    return res;
}

先将第一天入栈在判断第二天,所以要把while写在入栈的上边,不然第一天和自己开始比,最后结果全部为0

用一个栈记录天数,若栈为空则直接将天数入栈,答案数组记录至少需要等待的天数,若栈不为空且当前元素温度大于 栈顶所记录天数那天的温度,则给 答案数组中下标为栈顶所记录天数 的答案数组元素赋值为 当前天数 - 栈顶所记录天数 。若最终栈中还剩余天数也就是栈不为空的话证明后之后几天气温不会升高,该位置用0来代替,因此一开始需要要将答案数组赋值为0。最终返回答案数组。

/*法二:从后往前遍历,优化。
从前往后会超时,因此要从后往前比,答案数组中最后一天直接赋值为0,第二层循环中下标j每次自加储存在答案数组中的最少需要等待的天数即可,写为j+res[j],由于是从后往前遍历,i之后下标答案数组的中值是正确的,j在i之后,每次自增时若res[j]==0,说明此时的T[j]是T[i]之后最大元素了,此时若T[i]之后最大元素T[j]还小于T[i],说明T[i]之后没有比T[i]大的了,赋值res[i]=0;*/
int* dailyTemperatures(int* T, int TSize, int* returnSize){
    int *res = (int *)malloc(sizeof(int) * TSize);
    memset(res,0,TSize*sizeof(int));

    for (int i = TSize - 2; i >= 0; i--) {
        for (int j = i + 1; j <=TSize-1; j += res[j]) {//直接加到下一个比该数字大的数字,跳过所有比该数字小的数字。
            if (T[j] > T[i]) {
                res[i] = j - i;
                break;
            } else if (res[j] == 0) {//说明之后没有比它大的元素了,不必继续循环遍历,直接为0跳出循环;
                res[i] = 0;
                break;
            }
        }
    }
   *returnSize = TSize;
    return res;
}

从前往后比超时了。。。

/int dailyTemperatures(int T, int TSize, int* returnSize){

int res=(int)malloc(sizeof(int)*TSize);

memset(res,0,TSize*sizeof(int));

int flag=1;

for(int i=0;i<TSize;i++){

flag=0;

for(int j=i+1;j<TSize;j++){

  if(T[j]>T[i]){

    res[i]=j-i;

    flag=1;

    break;

  }

  if(flag) {

    //res[i]=0;

    break;

  }

}

}

  • returnSize=TSize;

return res;

}*/

LeetCode 234. 回文链表

请判断一个链表是否为回文链表。

示例 1:

输入: 1->2
输出: false

示例 2:

输入: 1->2->2->1
输出: true

进阶:
你能否用 O(n) 时间复杂度和 O(1) 空间复杂度解决此题?

bool isPalindrome(struct ListNode* head){
	struct ListNode*p1,*p2=p1=head;
	int count=0;
	while(p1){
		p1=p1->next;
		count++;
	}
    /*count是结点数*/
    if(count ==1) return true;
	p1=head;
	p2=head;

	for(int i=0;i<count/2-1;i++)
    {
		p2=p2->next;
	}
    /*二分之结点数减一是前半部分最后一个结点*/

    struct ListNode*p3=p2->next;
    p2->next=NULL;

    struct ListNode*pre=(struct ListNode*)malloc(sizeof(struct ListNode));
    pre->next=NULL;
    while(p3){
		struct ListNode*Next=p3->next;
        p3->next = pre;
        pre=p3;
        p3=Next;
	}
    /*转置完成p3从后往前遍历,p1从前往后遍历,一旦出现数字不一样return false*/
    while(p1&&pre){
        if(p1->val!=pre->val)
            return false;
        pre=pre->next;
        p1=p1->next;
    }
	return true;
}
/*先遍历结点数,然后控制p2走到前半部分最后一个结点,转置后半部分结点,然后控制p1和后半部分头结点依次比较,一旦出现数字不一样就不是回文。*/

LeetCode 19. 删除链表的倒数第 N 个结点

给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。

  • *进阶:**你能尝试使用一趟扫描实现吗?

示例 1:

https://www.icode9.com/i/ll/?i=img_convert/f9eb7e37e98bfb00965185a6095fcd8d.png

输入:head = [1,2,3,4,5], n = 2
输出:[1,2,3,5]

示例 2:

输入:head = [1], n = 1
输出:[]

示例 3:

输入:head = [1,2], n = 1
输出:[1]

提示:

  • 链表中结点的数目为 sz
  • 1 <= sz <= 30
  • 0 <= Node.val <= 100
  • 1 <= n <= sz
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
struct ListNode* removeNthFromEnd(struct ListNode* head, int n){
    struct ListNode* newhead= (struct ListNode*)malloc(sizeof(struct ListNode));
    newhead->next=head;
    struct ListNode*pfast=newhead,*pslow=newhead;
    n++;                    /*快指针多走一步,慢指针就能指向要删除结点的前一结点*/

    while(n){
        n--;
        pfast=pfast->next;
    }

    while(pfast){
        pfast=pfast->next;
        pslow=pslow->next;
    }
    //pslow->next = pslow->next->next;
    pfast = pslow->next;                        /*给pfast赋值*/
    pslow->next=pfast->next ;
    free(pfast);
    return newhead->next;
}

LeetCode 28. 实现 strStr()

实现 strStr() 函数。

给你两个字符串 haystackneedle ,请你在 haystack 字符串中找出 needle 字符串出现的第一个位置(下标从 0 开始)。如果不存在,则返回 -1

说明:

needle 是空字符串时,我们应当返回什么值呢?这是一个在面试中很好的问题。

对于本题而言,当 needle 是空字符串时我们应当返回 0 。这与 C 语言的 strstr() 以及 Java 的 indexOf() 定义相符。

示例 1:

输入:haystack = "hello", needle = "ll"
输出:2

示例 2:

输入:haystack = "aaaaa", needle = "bba"
输出:-1

示例 3:

输入:haystack = "", needle = ""
输出:0

提示:

  • 0 <= haystack.length, needle.length <= 5 * 104
  • haystackneedle 仅由小写英文字符组成
/*  int j = 0;要写在循环里边,不然像以下这样有很多个i的情况数组会越界。
    "mississippi"
    "issip"
每次遇到新的i要进行新一轮对比,直到haystack[i+j]!=needle[j++]或j==len2(完成字符串的比较)。若遍历完还没有满足情况,则return-1说明haystack中没有找到needle。
*/
int strStr(char * haystack, char * needle){
    int len1 = strlen(haystack),len2 = strlen(needle);
    if(!len2)
        return 0;
    for(int i=0;i<strlen(haystack);i++){
        int j=0;
        while(haystack[i+j]==needle[j++]){
            if(j==len2)
                return i;
        }
    }
    return -1;
}

1047. 删除字符串中的所有相邻重复项

给出由小写字母组成的字符串 S重复项删除操作会选择两个相邻且相同的字母,并删除它们。

在 S 上反复执行重复项删除操作,直到无法继续删除。

在完成所有重复项删除操作后返回最终的字符串。答案保证唯一。

示例:

输入:"abbaca"
输出:"ca"
解释:
例如,在 "abbaca" 中,我们可以删除 "bb" 由于两字母相邻且相同,这是此时唯一可以执行删除操作的重复项。之后我们得到字符串 "aaca",其中又只有 "aa" 可以执行重复项删除操作,所以最后的字符串为 "ca"。

char * removeDuplicates(char * S){
    int top = -1;
    char *stack = (char*)malloc(sizeof(char) * (strlen(S) + 1));
    for(int i=0;i<strlen(S);i++){
        if(top==-1 || S[i]!=stack[top]){    /*入栈的两种情况,1.栈为空。2.栈顶元素与当前遍历元素不相等*/
            stack[++top]=S[i];
        }
        else{
            top--;
        }
    }
    stack[++top]='\\0';
    return stack;
}

遍历字符串,若是栈为空或者栈顶元素与当前元素不相等则入栈,剩下情况出栈。判断时top==-1 写在前面,S[i]!=stack[top]写在后面,防止一开始top=-1造成数组越界。

LeeTcode1544. 整理字符串

给你一个由大小写英文字母组成的字符串 s

一个整理好的字符串中,两个相邻字符 s[i]s[i+1],其中 0<= i <= s.length-2 ,要满足如下条件:

  • s[i] 是小写字符,则 s[i+1] 不可以是相同的大写字符。
  • s[i] 是大写字符,则 s[i+1] 不可以是相同的小写字符。

请你将字符串整理好,每次你都可以从字符串中选出满足上述条件的 两个相邻 字符并删除,直到字符串整理好为止。

请返回整理好的 字符串 。题目保证在给出的约束条件下,测试样例对应的答案是唯一的。

  • *注意:**空字符串也属于整理好的字符串,尽管其中没有任何字符。

示例 1:

输入:s = "leEeetcode"
输出:"leetcode"
解释:无论你第一次选的是 i = 1 还是 i = 2,都会使 "leEeetcode" 缩减为 "leetcode" 。

示例 2:

输入:s = "abBAcC"
输出:""
解释:存在多种不同情况,但所有的情况都会导致相同的结果。例如:
"abBAcC" --> "aAcC" --> "cC" --> ""
"abBAcC" --> "abBA" --> "aA" --> ""

示例 3:

输入:s = "s"
输出:"s"

提示:

  • 1 <= s.length <= 100
  • s 只包含小写和大写英文字母
/*法一:暴力求解
char * makeGood(char * s){
    if(strlen(s)==1)
        return s;
    int len=strlen(s),j=0,top=-1;
    char *stack=(char*)malloc(sizeof(char)*len);
    for(int i=0;i<len;i++){
        while(s[i+1]==s[i]+32||s[i+1]==s[i]-32){
            for(int p=0;p<2;p++){
                for(int j=i;j<len;j++){
                    s[j]=s[j+1];
                }
            }
            i=0;
        }
    }
    s[strlen(s)]='\\0';
    return s;
}
遍历字符串,若是下一个字符与当前字符互为大小写,则后方所有字符前移两次,然后令i=0再次从头遍历,防止完成移动后前方再次形成新的互为大小写的相邻字符,因为每次都删除两个,所以时间其实很短。*/
/*法二:栈的妙用*/
char * makeGood(char * s){
    int len = strlen(s),top=-1;
    char *stack=(char*)malloc(sizeof(char)*1000);
    for(int i =0;i<len;i++){
        stack[++top] = s[i];
        if(top>=1)              /*弹出后指针不能比-1小*/
            if(abs(stack[top]-stack[top-1])==32)
                top-=2;
    }
    stack[++top]='\\0';
    return stack;
}
/*构建一个栈,依次入栈,然后判断栈顶元素是否与栈顶元素的前一个字符互为要删除的大小写字符,是的话弹出两个字符,继续遍历。要注意弹出后指针不能比-1小。*/

LeetCode 137. 只出现一次的数字 II

给你一个整数数组 nums ,除某个元素仅出现 一次 外,其余每个元素都恰出现 **三次 。**请你找出并返回那个只出现了一次的元素。

示例 1:

输入:nums = [2,2,3,2]
输出:3

示例 2:

输入:nums = [0,1,0,1,0,1,99]
输出:99

提示:

  • 1 <= nums.length <= 3 * 104
  • 231 <= nums[i] <= 231 - 1
  • nums 中,除某个元素仅出现 一次 外,其余每个元素都恰出现 三次
  • *进阶:**你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗?
int singleNumber(int* nums, int numsSize){
    int arr[32] = {0};
    for(int i=0;i<numsSize;i++)
    {
        for(int j=0;j<32;j++)
        {
            arr[j]+= (nums[i]>>j) &1;
        }
    }
    unsigned int ans=0;
    for(int j=31;j>=0;j--)
    {
        arr[j]%=3;
        ans<<=1;
        ans |=arr[j];
    }
    return ans;
}

法一:位运算(每一位分别算)

https://www.icode9.com/i/ll/?i=img_convert/3eed0d9e4cbf4564d3bd1aec37d83f10.png

一个int4个字节32位,先建立一个长度32的数组arr用来存每一个int所占每一个字节的和,然后分别对每一位的和进行余3,最后剩的二进制就代表只出现一次的数。然后用一个unsigned int (对unsigned int进行移位操作时,最高位不会有任何特殊性。无符号整数必须使用%u来打印对int进行移位操作时,必须考虑最高位,向右移位操作相当于 (有符号数值)/2。)用来将数组arr从31到0每一位逆序左移出来,然后将此数字返回。

其中 逆序取数字时用或来记录每位数字而不能用加,因为加是给此二进制数代表的十进制数+1,而加到二进制里会造成不同的情况。

法二:有限状态机(还没看懂)

https://www.icode9.com/i/ll/?i=img_convert/906d432d3e31670e6a0e2dba4304e718.png

https://www.icode9.com/i/ll/?i=img_convert/fc2a27732dbcad1e339aa4dae650baf5.png

https://www.icode9.com/i/ll/?i=img_convert/d9d8f29acc5b4c13e674ab4bbd830aa8.png

首先理解一件事:本题所涉及位运算满足交换律和结合律。因此对于乱序数组abcbccb进行累计位运算ret = abcbccb 等价于 ret = bbbccca。只需考虑简单有序的情况即可
因此上通过两个变量
once = (once ^ nums[i]) & (~twice);
twice = (twice ^ nums[i]) & (~once);
由于 b^b = 0; b & 0 = 0; b & (~b) = 0;可以得到如下表:
出现次数 1 2 3
once b 0 0
twice 0 b 0
出现3次的数字对结果贡献是0,出现一次的数字对结果贡献是自身。
因此循环结束之后once就是结果
代码

int singleNumber(int* nums, int numsSize){
    int once = 0;
    int twice = 0;
    for (int i = 0; i < numsSize; i++){
        once = (once ^ nums[i]) & (~twice);
        twice = (twice ^ nums[i]) & (~once);
    }
    return once;
}

作者:dong-bei-zhang-da-shuai
链接:https://leetcode-cn.com/problems/single-number-ii/solution/cyu-yan-jie-jin-shuang-bai-wei-yun-suan-yuan-li-xi/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

1.为什么return one?

只有一位数的话肯的存在one上。

2.two公式为什么和one一样

画个图发现的。两个变量交换后一模一样。

https://www.icode9.com/i/ll/?i=20210421213417163.jpg?,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzUzNzQ5MjY2,size_16,color_FFFFFF,t_70

LeetCode 682. 棒球比赛

你现在是一场采用特殊赛制棒球比赛的记录员。这场比赛由若干回合组成,过去几回合的得分可能会影响以后几回合的得分。

比赛开始时,记录是空白的。你会得到一个记录操作的字符串列表 ops,其中 ops[i] 是你需要记录的第 i 项操作,ops 遵循下述规则:

  1. 整数 x - 表示本回合新获得分数 x
  2. "+" - 表示本回合新获得的得分是前两次得分的总和。题目数据保证记录此操作时前面总是存在两个有效的分数。
  3. "D" - 表示本回合新获得的得分是前一次得分的两倍。题目数据保证记录此操作时前面总是存在一个有效的分数。
  4. "C" - 表示前一次得分无效,将其从记录中移除。题目数据保证记录此操作时前面总是存在一个有效的分数。

请你返回记录中所有得分的总和。

示例 1:

输入:ops = ["5","2","C","D","+"]
输出:30
解释:
"5" - 记录加 5 ,记录现在是 [5]
"2" - 记录加 2 ,记录现在是 [5, 2]
"C" - 使前一次得分的记录无效并将其移除,记录现在是 [5].
"D" - 记录加 2 * 5 = 10 ,记录现在是 [5, 10].
"+" - 记录加 5 + 10 = 15 ,记录现在是 [5, 10, 15].
所有得分的总和 5 + 10 + 15 = 30

示例 2:

输入:ops = ["5","-2","4","C","D","9","+","+"]
输出:27
解释:
"5" - 记录加 5 ,记录现在是 [5]
"-2" - 记录加 -2 ,记录现在是 [5, -2]
"4" - 记录加 4 ,记录现在是 [5, -2, 4]
"C" - 使前一次得分的记录无效并将其移除,记录现在是 [5, -2]
"D" - 记录加 2 * -2 = -4 ,记录现在是 [5, -2, -4]
"9" - 记录加 9 ,记录现在是 [5, -2, -4, 9]
"+" - 记录加 -4 + 9 = 5 ,记录现在是 [5, -2, -4, 9, 5]
"+" - 记录加 9 + 5 = 14 ,记录现在是 [5, -2, -4, 9, 5, 14]
所有得分的总和 5 + -2 + -4 + 9 + 5 + 14 = 27

示例 3:

输入:ops = ["1"]
输出:1

int calPoints(char ** ops, int opsSize){
    int stack[opsSize],top = -1,sum = 0; // 累计得分
    for(int i = 0; i < opsSize; i++) {
        switch(ops[i][0]) {
            case 'D' :
                stack[++top] = stack[top] * 2;
                sum += stack[top];
                break;
            case '+' :
                stack[++top] = stack[top] + stack[top - 1];
                sum += stack[top];
                break;
            case 'C' :
                sum -= stack[top--];
                break;
            default :
                stack[++top] = atoi(ops[i]);
                sum += stack[top];
        }
    }
    return sum;
}

LeetCode147. 对链表进行插入排序

对链表进行插入排序。

https://www.icode9.com/i/ll/?i=img_convert/9400029b6559a5f16c48610324ceb961.png

插入排序的动画演示如上。从第一个元素开始,该链表可以被认为已经部分排序(用黑色表示)。
每次迭代时,从输入数据中移除一个元素(用红色表示),并原地将其插入到已排好序的链表中。

插入排序算法:

  1. 插入排序是迭代的,每次只移动一个元素,直到所有元素可以形成一个有序的输出列表。
  2. 每次迭代中,插入排序只从输入数据中移除一个待排序的元素,找到它在序列中适当的位置,并将其插入。
  3. 重复直到所有输入数据插入完为止。

示例 1:

输入: 4->2->1->3
输出: 1->2->3->4

示例 2:

输入: -1->5->3->4->0
输出: -1->0->3->4->5

通过次数83,532

提交次数123,925

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 1.后面如果大的话,把后面大的插到前面去。
 2.要先用p把c分离出来再把c插入前面,否则指向会出错
 3.t->next的值大于c,c插入t和t->next之间*/
struct ListNode *insertionSortList(struct ListNode *head) {
    if(!head||!head->next)
        return head;
    struct ListNode *newhead=(struct ListNode *)malloc(sizeof(struct ListNode)),*t,*p,*c;
    newhead->next=head;
    c = head;
    p = newhead;
    while(c){
        if(p->val>c->val){
            t=newhead;
            while(t->next->val < c->val)
            {
                t=t->next;
            }
            p->next=p->next->next;              /*要先用p把c分离出来再把c插入前面,否则指向会出错*/
            c->next=t->next;                    /*t->next的值大于c,c插入t和t->next之间*/
            t->next=c;
        }else{
            p=p->next;
        }
        c=p->next;
    }
    return newhead->next;
}

LeetCode844. 比较含退格的字符串

给定 ST 两个字符串,当它们分别被输入到空白的文本编辑器后,判断二者是否相等,并返回结果。 # 代表退格字符。

  • *注意:**如果对空文本输入退格字符,文本继续为空。

示例 1:

输入:S = "ab#c", T = "ad#c"
输出:true
解释:S 和 T 都会变成 “ac”。

示例 2:

输入:S = "ab##", T = "c#d#"
输出:true
解释:S 和 T 都会变成 “”。

示例 3:

输入:S = "a##c", T = "#a#c"
输出:true
解释:S 和 T 都会变成 “c”。

示例 4:

输入:S = "a#c", T = "b"
输出:false
解释:S 会变成 “c”,但 T 仍然是 “b”。

提示:

  • 1 <= S.length <= 200
  • 1 <= T.length <= 200
  • ST 只含有小写字母以及字符 '#'

进阶:

  • 你可以用 O(N) 的时间复杂度和 O(1) 的空间复杂度解决该问题吗?
/*  1.strcmp(str1,str2),若str1=str2,则返回零
   2.if(t[i]=='#' && top>0)忘了加&& top>0
   3.当top==-1时也得判断是否为'#',无法退格但是不能入栈*/
/*"y#fo##f"
 "y#f#o##f"*/
bool backspaceCompare(char * s, char * t){
   char stack1[strlen(s)+1],stack2[strlen(t)+1];
   int top= -1;
   for(int i=0  ;i<strlen(s) ; i++){
       if(s[i]=='#' && top>=0)
           top--;
       else if(s[i]!='#')
           stack1[++top]=s[i];
   }

   stack1[++top]='\\0';

   top= -1;
   for(int i=0; i<strlen(t) ;i++){
       if(t[i]=='#' && top>=0)
           top--;
       else if(t[i]!='#')
           stack2[++top]=t[i];
   }
   stack2[++top]='\\0';
   if(strcmp(stack1,stack2)==0)
       return true;
   else
       return false;
}

1598. 文件夹操作日志搜集器

难度简单14

每当用户执行变更文件夹操作时,LeetCode 文件系统都会保存一条日志记录。

下面给出对变更操作的说明:

  • "../" :移动到当前文件夹的父文件夹。如果已经在主文件夹下,则 继续停留在当前文件夹
  • "./" :继续停留在当前文件夹**。**
  • "x/" :移动到名为 x 的子文件夹中。题目数据 保证总是存在文件夹 x

给你一个字符串列表 logs ,其中 logs[i] 是用户在 ith 步执行的操作。

文件系统启动时位于主文件夹,然后执行 logs 中的操作。

执行完所有变更文件夹操作后,请你找出 返回主文件夹所需的最小步数

示例 1:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QB5f8laP-1619619986508)(D:/Program Files/TyporaPicture/sample_11_1957.png)]

输入:logs = ["d1/","d2/","../","d21/","./"]
输出:2
解释:执行 "../" 操作变更文件夹 2 次,即可回到主文件夹

示例 2:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nGSLozJT-1619619986510)(D:/Program Files/TyporaPicture/sample_22_1957.png)]

输入:logs = ["d1/","d2/","./","d3/","../","d31/"]
输出:3

示例 3:

输入:logs = ["d1/","../","../","../"]
输出:0

/*遇到 ../,返回主文件的层级 -1。
遇到 ./,返回主文件的层级无变化。
因为x/时x为子文件夹
遇到 x/,返回主文件的层级 +1。*/
int minOperations(char ** logs, int logsSize){
    int sum = 0;
    for(int i =0;i < logsSize;i++){
        if(!strcmp(logs[i],"./"))
            continue;
        else if(!strcmp(logs[i],"../")){                /*必须加大括号,不然else会和if(sum>0)匹配*/
                if(sum>0)
                    sum-=1;
        }
        else
            sum++;
    }
    return sum;
}

1290. 二进制链表转整数

难度简单80

给你一个单链表的引用结点 head。链表中每个结点的值不是 0 就是 1。已知此链表是一个整数数字的二进制表示形式。

请你返回该链表所表示数字的 十进制值

示例 1:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-o4XDTTM8-1620536982489)(D:/Program Files/TyporaPicture/graph-1.png)]

输入:head = [1,0,1]
输出:5
解释:二进制数 (101) 转化为十进制数 (5)

示例 2:

输入:head = [0]
输出:0

示例 3:

输入:head = [1]
输出:1

示例 4:

输入:head = [1,0,0,1,0,0,1,1,1,0,0,0,0,0,0]
输出:18880

示例 5:

输入:head = [0,0]
输出:0

int getDecimalValue(struct ListNode* head){
   struct ListNode*p=head;
   int ans=0;

   while(p)
   {
       ans=(ans<<1) | p->val;
       p=p->next;
   }

   return ans;
}

位运算,每次数字代表的二进制左移一位,然后将链表中的0或1 或 操作进去前面都是0不改变,只改变最后一位。

LeetCode283. 移动零

难度简单1056

给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。

示例:

输入: [0,1,0,3,12]
输出: [1,3,12,0,0]

void moveZeroes(int* nums, int numsSize){
    int left=0,right=0;
    for(right=0;right<numsSize;right++)
    {
        if(nums[right]!=0)
        {
            int t=nums[right];
            nums[right]=nums[left];
            nums[left]=t;
            left++;
        }
    }
}

双指针遍历数组,right遍历数组,left左边为不为0的数组,right指向为0则继续遍历,若不为0则与left交换然后left++,这样left左边就全是非0数且次序不会变,left和right一开始就指向同一非0数的话也进行交换同时令left++,直到left指向0然后令right前进直到指向非数交换。

LeetCode200. 岛屿数量

难度中等1143

给你一个由 '1'(陆地)和 '0'(水)组成的的二维网格,请你计算网格中岛屿的数量。

岛屿总是被水包围,并且每座岛屿只能由水平方向和/或竖直方向上相邻的陆地连接形成。

此外,你可以假设该网格的四条边均被水包围。

示例 1:

输入:grid = [
  ["1","1","1","1","0"],
  ["1","1","0","1","0"],
  ["1","1","0","0","0"],
  ["0","0","0","0","0"]
]
输出:1

示例 2:

输入:grid = [
  ["1","1","0","0","0"],
  ["1","1","0","0","0"],
  ["0","0","1","0","0"],
  ["0","0","0","1","1"]
]
输出:3

void dfs(int row,int col,int a,int b,char **grid){
   int dir[4][2] = {{0,1},{1,0},{0,-1},{-1,0}};
   if( a>=row || b>=col || a<0 || b<0 || grid[a][b] == '0')              //需要注意:判断放在前面
   {
       return ;
   }
   else
   {
       grid[a][b] = '0';
   }
   for(int i=0;i<4;i++)
   {
       int aa = a + dir[i][0];
       int bb = b + dir[i][1];
       dfs(row,col,aa,bb,grid);
   }
}

int numIslands(char** grid, int gridSize, int* gridColSize){
   int row = gridSize,count=0;
   int col = gridColSize[0];

   for(int i=0;i<row;i++)
   {
       for(int j=0;j<col;j++)
       {
           if( grid[i][j] == '1')
           {
               dfs(row,col,i,j,grid);
               count++;
           }
       }
   }

   return count;
}

深搜,先遍历每个格子,如果是0就跳过,如果是1就用深搜函数每个格子按右下左上的顺序将1变成0,先从此结点右方右开始将1变成0,然后返回上一个结点,再按右下左上的顺序,依次遍历,每一次这样即可完成将一块岛屿变成0。统计每一块的数量。

标签:ListNode,struct,int,样例,next,链表,错题,C语言
来源: https://blog.csdn.net/qq_53749266/article/details/119083990

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有