打卡leetcode第16天

目录

1.删除链表中倒数第n个结点

2.字符串的排列

3.图像渲染

4.合并两个有序链表

5.反转链表


1.删除链表中倒数第n个结点

【题目】

 

【分析】

法1:计算链表长度

int getlength(struct ListNode* head){
    int i=0;
    
    while(head!=NULL){
        head=head->next;
        i++;
    }
    return i;
}
struct ListNode* removeNthFromEnd(struct ListNode* head, int n){
      int len=getlength(head);
      
      struct ListNode* L=malloc(sizeof(struct ListNode));
      L->val=0;
      L->next=head;
      struct ListNode *cur=L;
      for(int i=1;i<len-n+1;i++){
          cur=cur->next;
      }
      cur->next=cur->next->next;
      struct ListNode* ans=L->next;
      free(L);
      return ans;

}

法2:双指针

struct ListNode* removeNthFromEnd(struct ListNode* head,int n){
       struct ListNode* L=malloc(sizeof(struct ListNode));
       L->val=0;
       L->next=head;
       struct ListNode* p=L;//p是前驱结点
       struct ListNode* q=L;
       for(int i=0;i<n+1;i++){
           q=q->next;
       }
       while(q){
           p=p->next;
           q=q->next;
       }
       struct ListNode* delNode = p->next;
       p->next=delNode->next;
       struct ListNode* ans=L->next;
       free(L);
       return ans;

}

2.字符串的排列

【题目】

【分析】

bool checkInclusion(char* s1, char* s2) {
   int n = strlen(s1), m = strlen(s2);//n,m分别对应1,2的长度
   if (n > m) {//如果字符串1大于字符串2的长度直接返回false
       return false;
   }
   int cnt[26];//建立小写字母数组
   memset(cnt, 0, sizeof(cnt));//为每个字母对应的数组空位置0
   for (int i = 0; i < n; ++i) {
       --cnt[s1[i] - 'a'];//将字符串1内的字符进行统计(按负数统计)
   }
   int left = 0;
   for (int right = 0; right < m; ++right) {
       int x = s2[right] - 'a';//获取right对应字母在cnt中的位置
       ++cnt[x];//计数加一
       while (cnt[x] > 0) {     //该字母数在字符串2内的数目大于字符串1 大于0的都是s2有s1没有的字符
           --cnt[s2[left] - 'a'];      //left对应字母在cnt中计数减1
           ++left;                     //left右移
       }
       if (right - left + 1 == n) {    //若左右指针间长度等于s1的长度
           return true;                //返回true
       }
   }
   return false;
}

3.图像渲染

【题目】

 

 

【分析】

imageSize的意思是行的长度,
imageColSize对应每一列的长度(注意是数组),
sr为选定值的x坐标
sc为选定值的y坐标

类似于递归,由于给出初始的块,并且已知初始的颜色,且该图是一个二维图,所以只有上下左右四个邻接。

实现邻接:假如初始的坐标为[1,1],那么和初始坐标邻接的就是(1,0),(1,2),(0,1),(2,1)
为了实现坐标的更迭,定义相应的函数来更迭坐标的位置,该题中可以设dx,dy来实现。
设dx[4]={0,0,-1,1};dy[4]={1,-1,0,0};

之后坐标只要将其自身的x+dx[i],y+dy[i],就可以实现同时四个方向的搜索,类似于递归的找法,直到x出规定范围,y出规定范围,就可以返回原图,实现颜色替换。

//  const int dx[4]={0,0,-1,1};
//  const int dy[4]={1,-1,0,0};
// //定义用于之后的查找,由于是找出邻接的四个单位,
// //所以就是(x,y+1)(上),(x,y-1)(下),(x-1,y)(左),(x+1)(右)。
// //tips:为了能够完成该操作,在对应的dx[i]和对应的dy[i]中要实现对应的数,下面的A中可以看到

//  void dfs(int **image,int imageSize,int *imageColSize,int x,int y,int curcolor,int newcolor)
//  {
//   if(x<0||x>=imageSize||y<0||y>=imageColSize[0]){
//   return;
// }
// //判断是否越界,如果越界直接返回。
// //tips:imageColSize[0]不能漏掉[0],因为imageColSize原名imagecolumnsize,
// //对应每列的长度并且在输入值时,输入的就是数组,所以要用它本身的元素
//  if(image[x][y]==curcolor)
//  {
//   image[x][y]=newcolor;
// //替换颜色
//   for(int i=0;i<4;i++)
//   {
//       int nx=x+dx[i];
//       int ny=y+dy[i];
// //A操作,i=0,1,2,3分别对应上下左右新定义nx,ny,并且判断nx,ny是否越界用于下面的深度优先查找
//       if(nx>=0&&nx<imageSize&&ny>=0&&ny<imageColSize[0])
//       {
//        dfs(image,imageSize,imageColSize,nx,ny,curcolor,newcolor);
//       }
//   }
//  }
//  return;
//  }


// int** floodFill(int** image, int imageSize, int* imageColSize, int sr, int sc, int newColor, int* returnSize, int** returnColumnSizes){
// *returnSize=imageSize;
// *returnColumnSizes=imageColSize;
// if(image[sr][sc]!=newColor){
// dfs(image,imageSize,imageColSize,sr,sc,image[sr][sc],newColor);
// }
// //要先判断是否和新颜色相同,用例中有原来就是新颜色不需要更改的例子
// return image;
// }

4.合并两个有序链表

【题目】

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

【分析】

 1.递归

2.迭代

//递归
struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2){

      if(list1==NULL){
          return list2;
          }
      if(list2==NULL){
          return list1;
      }
      //list1 , list2 都存在的情况,使用递归进行求解
    if(list1->val < list2->val) {
        list1->next = mergeTwoLists(list1->next, list2);
        return list1;
    } 
    else {
        list2->next = mergeTwoLists(list1, list2->next);
        return list2;
    }
}
//双指针迭代
struct ListNode* mergeTwoLists(struct ListNode* l1, struct ListNode* l2){
    struct ListNode* l3 = (struct ListNode *)malloc(sizeof(struct ListNode));
    struct ListNode* p1 = l1, * p2 = l2; 
    struct ListNode* r3 = l3;
    while(p1 && p2){
        if((p1 -> val) <= ( p2 -> val)){
            r3 -> next = p1;
            r3 = p1;
            p1 = p1 -> next;
        }
        else{
          
          r3 -> next = p2;
          r3 = p2; 
          p2 = p2->next;
        }
    }
    if(!p1)
       { r3 -> next = p2 ; }
    else if(!p2)
        { r3 -> next = p1; } 
    return l3->next;
}

5.反转链表

【题目】

【分析】

迭代,递归

//迭代
struct ListNode* reverseList(struct ListNode* head){
      struct ListNode* prev=NULL;
      struct ListNode* cur=head;
      while(cur){
          struct ListNode* next=cur->next;
          cur->next=prev;
          prev=cur;
          cur=next;
      }
      return prev;
}
//递归
struct ListNode* reverseList(struct ListNode* head) {
    if (head == NULL || head->next == NULL) {
        return head;
    }
    struct ListNode* newHead = reverseList(head->next);
    head->next->next = head;
    head->next = NULL;
    return newHead;
}

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值