Leetcode里面的题

在这里插入图片描述
此时定义了三个变量,一个为dst,prev和cur,那么为什么会这么想呢?
在这里插入图片描述

int removeDuplicates(int* nums, int numsSize)
{
    
    
   //数组在一开始的时候有可能为空,这个情况也一定要考虑进去
   if (numsSize == 0)
		return 0;
	int prev = 0, cur = 1, dst = 0;
	while (cur < numsSize) //用cur来判断,因为他最终会越界,作为循环来结束的一个判断标志,prev指向数组中下标为0的元素,cur指向数组中下标为1的元素
	{
    
    
		if (nums[prev] != nums[cur])
		{
    
    
			nums[dst] = nums[prev];
			prev++;
			dst++;
			cur++;
		}
		else
		{
    
    
			prev++;
			cur++;
		}
	}
	//此时prev和cur的值是不相等的,但是上面你只返回了prev的值,
	//最后一个cur值也是需要返回的
	nums[dst] = nums[prev];
	dst++;
	return dst;
}


在这里插入图片描述

提示:
1 <= A.length <= 10000
0 <= A[i] <= 9
0 <= K <= 10000
如果 A.length > 1,那么 A[0] != 0

1.考虑K这个值为几位数
2.结果要求输出的是一个数组,但是你这个数组应该开辟多大的呢?(最大的那个数组元素位数加1,不可能在超过这个数字了,是在不行其实是可以直接开辟一个6位整形的空间)
3.返回的那个数组来存储你的每个位数,但是你会发现是先从个位数相加的,所以你的返回数组的顺序是反的,最终需要在颠倒过来。

int* addToArrayForm(int* A, int ASize, int K, int* returnSize)
{
    
    
	//计算K是多少位的
	int KSize = 0;
	int kNum = K; // 如果不加这个你会发现,你到最后把K的数值已经改变了,就找不到了
	while (kNum)
	{
    
    
		KSize++;
		kNum /= 10; // 这里也在提示不要轻易的修改掉原来的K值,因为这里会发生K值的变化
	}
	int len = ASize > KSize ? ASize : KSize;
	int* retArr = (int*)malloc(sizeof(int)*(len+1)); //返回数组的长度,但是这里还有一个小技巧,你会发现题目下面是有限制条件的,0<K<10000
	//所以你就直接开辟一个6位数数组大小空间就好了。

	//A []
	//K
	int Ai = ASize - 1; //A数组的最后一位
	int reti = 0;
	int nextNum = 0;//进位
	while (len--)
	{
    
    
		int a = 0;
		if (Ai >= 0) // A的数组短,会先走完
		{
    
    
			a = A[Ai];
			Ai--;
		}
		int ret = a + K % 10 + nextNum;
		K /= 10;
		if (ret > 9)
		{
    
    
			ret -= 10;
			nextNum = 1;
		}
		else
		{
    
    
			nextNum = 0;
		}
		retArr[reti] = ret;
		reti++;
	}
	if (nextNum == 1)
	{
    
    
		retArr[reti] = 1;
		reti++;
	}
	//逆置
	int left = 0;
	int right = reti - 1;
	while (left < right)
	{
    
    
		int tmp = retArr[left];
		retArr[left] = retArr[right];
		retArr[right] = tmp;
		left++;
		right--;
	}
	*returnSize = reti;
	return retArr;
}

在这里插入图片描述
这个题很巧妙的使用了prev和cur指针,开始的时候perv这个指针是在NULL地方的。而且要考虑到一开始就是你要找的那个val值的情况。
在这里插入图片描述

struct ListNode* removeElements(struct ListNode* head, int val)
{
    
    
    //对于head不要轻易的作出修改,因为他最终让你返回的是这个单链表的头,所以能不修改尽量不要修改
    struct ListNode* prev = NULL,*cur = head;
    while(cur != NULL)
    {
    
    
        if(cur->val == val) // 这个地方的逻辑是混乱的,需要重新看视频理解代码
        {
    
    
            if(cur == head) //第一个值就是val
            {
    
    
               head = cur->next;
               free(cur);
               cur = head;
            }
            else//(不是第一个位置为6的可能性)
            {
    
    
                prev->next=cur->next;
                free(cur);//如果不添加最后这行代码,你就会发现此时cur已经被free变成野指针了,你在上去
                //进行使用它,就会报错
                cur = prev->next;  // 原来会写cur = cur->next,这样写也是错误的,因为你会发现,你的cur已经被释放了,然后你在下一行中还要使用它,所以我们使用prev来定义它此时的cur
            }
        }
        else
        {
    
    
            prev = cur;
            cur = cur->next;
        }
    }
    return head;
}

第二种方法:三指针翻转法

struct ListNode* reverseList(struct ListNode* head)
{
    
    
     if(head == NULL || head->next == NULL)
    {
    
    
        return head;
    }
    struct ListNode* n1 = NULL;
    struct ListNode* n2 = head;
    struct ListNode* n3 = head->next;
    while(n2 != NULL)
    {
    
    
        n2->next = n1;
        n1 = n2;
        n2 = n3;
//循环的条件是判断n2,但是当n2指向链表的最后一个结点的时候,n3已经在NULL的位置了,如果你不它加以判断,而是直接的解引用,程序就会崩溃。
        if(n3 != NULL)
        {
    
    
           n3 = n3->next; 
        }
    }
    return n1;
}

在这里插入图片描述

对于这个题就比较有意思了,定义了一个cur和newHead的NULL空指针,此时相当于我把原先链表的头拿下来然后进行头插在newHead的前面
在这里插入图片描述

struct ListNode* reverseList(struct ListNode* head)
{
    
    
    struct ListNode* newHead = NULL;
    //然后我进行头插,插到我新建的这个newhead前面
	struct ListNode* cur = head;
	while (cur != NULL)
	{
    
    
        struct ListNode* next = cur->next;
		cur->next = newHead;
		newHead = cur;
		cur = next;
	}
	return newHead;
}

在这里插入图片描述

//首先让小的那个做为头,然后并的比较,当有一个链表为NULL的时候就停止了,剩下的直接拉下来就好了
struct ListNode* mergeTwoLists(struct ListNode* l1, struct ListNode* l2)
{
    
    
   //当着两个都不为空的时候再回进入到第三个if里面
    if(l1 == NULL)
        return l2;
    if(l2 == NULL)
        return l1;
    if(l1 == NULL && l2 == NULL)//这样写就会很轻易的理解对于l1和l2是由4种可能性的。
        return ;
     struct ListNode* head = NULL,*tail = NULL;
     //带哨兵位的头结点,没有实际的数据
   
        //你如果不进行上面的判断,你会发现,你在下面用到了结构体的解引用,程序直接有可能崩溃
    if(l1->val < l2->val)
    {
    
    
        head = tail = l1;
        l1 = l1->next;
    } 
    else
    {
    
    
        head = tail = l2;
        l2 = l2->next;
    }
    //取较小的值进行尾插
    while(l1 && l2)
    {
    
    
        if(l1->val < l2->val)
        {
    
    
            tail->next = l1;
            l1 = l1->next;
        }
        else
        {
    
    
            tail->next = l2;
            l2 = l2->next;
        }
         tail = tail->next;
    }
    if(l1)
    {
    
    
         tail->next = l1;
    }
    else
    {
    
    
         tail->next = l2;
    }
    return head;
}

猜你喜欢

转载自blog.csdn.net/MEANSWER/article/details/111605366
今日推荐