数据结构树和二叉树的学习使用&数据结构栈,队列,链表的学习使用

数据结构树和二叉树的学习使用&数据结构栈,队列,链表的学习使用

task在此

LeetCode题号:20. 有效的括号(简单)给定一个只包括 ‘(’,’)’,’{’,’}’,’[’,’]’ 的字符串,判断字符串是否有效。

思路:
1.初始化一个栈stack,定义一个指向栈顶元素的指针变量top
2.依次读取字符串内中的每一个字符;
3.遇到左括号‘(’,’[’,’{'则进栈,top+1;
遇到右括号,检查栈顶元素是否与之对应,若不对应,返回false;
若对应,则指向栈顶元素的指针top-1,指向栈内下一个元素。
直到读取完字符串,出现不匹配现象(返回 false)
读取完字符串后,栈内还有元素(返回false)

bool isValid(char * s){
 if (s == NULL || s[0] == '\0') return true;//判断字符串s是否为空串
    char *stack = (char*)malloc(strlen(s)+1); //为栈stack分配内存空间
    int i,top=0;//用top指向栈顶元素
    for (i = 0; s[i]; i++) {
        if (s[i] == '(' || s[i] == '[' || s[i] == '{') stack[top++] = s[i];//若为左括号,则进栈
        else {
            if ((--top) < 0)                      return false;//判断栈中是否还有元素
            if (s[i] == ')' && stack[top] != '(') return false;
            if (s[i] == ']' && stack[top] != '[') return false;
            if (s[i] == '}' && stack[top] != '{') return false;
            
        }
    }  
       if(top!=0) return false;//判断读取完字符串后栈中是否还有元素
    free(stack);//释放内存空间
    return(true);
}
LeetCode题号: 150. 逆波兰表达式求值(中等)根据逆波兰表示法,求表达式的值。有效的运算符包括 +, -, *, / 。每个运算对象可以是整数,也可以是另一个逆波兰表达式。

思路:
1.初始化一个栈stack,定义一个指向栈顶元素的变量top
2.将遇到的数字依次存入栈中若遇到的字符串为非数字,如+、-、*、/等,取出栈中的前两个元素num1,num2进行运算,并将结果再压入栈中。

int evalRPN(char ** tokens, int tokensSize){
    int stack[10000], top = 0;
    int num1, num2;
    int i;
    for(i = 0; i < tokensSize; i++)
    {
        if(tokens[i][1] == '\0'&& (tokens[i][0] == '+' || tokens[i][0] == '-' || tokens[i][0] == '*' || tokens[i][0] == '/') ){//若无tokens[i][1] == '\0',则读入负数时会使程序报错
            num2 = stack[--top]; 
            num1 = stack[--top];
            switch(tokens[i][0]){//用switch_case语句确定不同的情况类型
                case '-' :
                    stack[top++] = num1 - num2;
                    break;
                case '+' :
                    stack[top++] = num1 + num2;
                    break;
                case '*' :
                    stack[top++] = num1 * num2;
                    break;
                case '/' :
                    stack[top++] = num1 / num2;
                    break;
                default :
                    break;
            }
        }else{
            stack[top++] = atoi(tokens[i]);//用atoi函数将字符串转化为数据输出,并存入栈中
        }   
    }
    
    return stack[--top];
}
LeetCode题号: 42.给定n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后最多能接多少雨水

在这里插入图片描述

上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度图,可以接 6 个单位的雨水(蓝色部分表示雨水)

思路:
假设以第i个柱子为接水的起始边界,那么可以分为两种情况:
1.柱子 i 后面存在柱子 j ,其高度大于等于柱子 i,我们可以以height[i]为较低边界,在[i,j]之间接水。 那么柱子[i,j]之间可接水: (j - i - 1)* height[i] - sum(i,j) ,其中sum(i,j)表示(i,j)之间柱子的高度之和,不包括i,j。
2.柱子 i 后面不存在高度大于等于height[i]的柱子 ,并假设 i 后面的柱子的最大高度为 height[j] = t, 我们可以以height[i]为较高边界,在[i,j]之间接水。 那么柱子[i,j]之间可接水: (j - i - 1)* t - sum(i,j) 。

class Solution {
public:
    int trap(vector<int>& height) {
        int n = height.size();
        if(n == 0) return 0;
        int ans = 0;
        int sum[n];
        sum[0] = height[0];
        for(int i=1;i<n;i++) sum[i] = sum[i-1] + height[i];
        int maxd[n];
        maxd[n-1] = height[n-1];
        for(int i=n-2;i>=0;i--) maxd[i] = max(maxd[i+1],height[i]);
        int i=0, tmp =0;
        while(height[i] == 0) i++;
        while(i < n-1)
        {
            if(maxd[i+1] >= height[i])
            {
                int j = i+1;
                while(height[j] < height[i]) j++;
                tmp = (j-i-1)*height[i];
                tmp -= sum[j-1] - sum[i];
                ans += tmp;
                i = j;
            }
            else
            {
                int t = maxd[i+1];
                int j = i+1;
                while(height[j] < t) j++;
                tmp = (j-i-1)*t;
                tmp -= sum[j-1] - sum[i];
                ans += tmp;
                i = j;
            }
        }
        return ans;
    }
};
LeetCode题号: 21. 合并两个有序链表(简单)
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
        ListNode temp_head(0);  //设置临时头节点temp_head
        ListNode *ptr = &temp_head; //使用pre指针指向temp_head
        while(l1&&l2){  //l1和l2不空时,对它们进行比较
            if(l1->val < l2->val){   //如果l1对应的节点小于l2对应的节点
                ptr->next = l1;   //将ptr与较小的节点进行连接
                l1 = l1->next;
            }
            else{
                ptr->next = l2;
                l2 = l2->next;
            }
            ptr = ptr->next;  //ptr指向新连接的节点
        }
        if(l1){  //如果l1有剩余
            ptr->next = l1;   //将l1接到ptr后
        }
        if(l2){
            ptr->next = l2;  //将l2接到ptr后
        }
        return temp_head.next;
    }
};
LeetCode题号: 2. 两数相加
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
struct ListNode* addTwoNumbers(struct ListNode* l1, struct ListNode* l2){
    //遍历两个链表,已得到二者各自的长度
    struct ListNode*last1=l1;//定义last1以便于遍历l1(last指向最后一个节点)
    int len1=0,len2=0,len;
    for(;last1->next;len1++){
        last1=last1->next;
    }
    struct ListNode*last2=l2;//定义last2以便于遍历l2(last指向最后一个节点)
    for(;last2->next;len2++){
        last2=last2->next;
    }
    //比较两个链表的长度,短的链表延长并用零补齐
    if(len1<len2){
        len=len2;
        for(int i=0;i<len2-len1;i++){
            struct ListNode*pn=(struct ListNode*)malloc(sizeof(struct ListNode));//定义指向新节点的pn,以创建新节点
            pn->val=0;
            pn->next=NULL;
            last1->next=pn;//把新节点接到last1上去
            last1=last1->next;
        }
    }
    else if(len1>len2){
        len=len1;
        for(int i=0;i<len1-len2;i++){
            struct ListNode*pn=(struct ListNode*)malloc(sizeof(struct ListNode));//定义指向新节点的pn,以创建新节点
            pn->val=0;
            pn->next=NULL;
            last2->next=pn;//把新节点接到last2上去
            last2=last2->next;
        }
    }
    //两个链表对应节点分别求和,并将结果放到第三个链表对应节点处
    struct ListNode*p3=(struct ListNode*)malloc(sizeof(struct ListNode));//新建用于储存结果的新链表p3
    int mod=0;//定义决定进位的余数
    p3->next=NULL;
    p3->val=(l1->val+l2->val+mod)%10;
    mod=(l1->val+l2->val+mod)/10;
    struct ListNode*last3=p3;//定义指向尾部的指针
    l1=l1->next;
    l2=l2->next;
    for(int i=0;i<len;i++){
        struct ListNode*node=(struct ListNode*)malloc(sizeof(struct ListNode));//新节点
        node->next=NULL;
        node->val=(l1->val+l2->val+mod)%10;
        mod=(l1->val+l2->val+mod)/10;
        last3->next=node;//新节点加到新链表上
        last3=last3->next;
        l1=l1->next;
        l2=l2->next;
         
    }
    return p3;
} 
LeetCode题号: 25. K 个一组翻转链表 (困难)

示例 :
给定这个链表:1->2->3->4->5
当 k = 2 时,应当返回: 2->1->4->3->5
当 k = 3 时,应当返回: 3->2->1->4->5
借鉴思路
使用栈存储k个数据,每存储 st.size() == k ,则进行一次反转;
每次循环要记录返回的链表的最后一个节点 nextline , 为了链接下一个反转的首节点;
当st.size() < k 时,则将nextline->next = st 中的最下面的元素;

迭代法

class Solution {
    public ListNode reverseKGroup(ListNode head, int k) {
        int size = 0;
        ListNode countNode = head;
        while(countNode != null){
            countNode = countNode.next;
            size++;
        }
        if(size < k) return head;
        
        ListNode curtail = null;
        ListNode pre = head;
        ListNode prelast = null;
        ListNode cur, rear, first, last;
        int count = 0;
        
        while(count < size / k){
            first = pre;
            last = pre;
            int index = 1;
            cur = pre.next;
            while(index < k){
                rear = cur.next;
                cur.next = pre;
                last = cur;
                pre = cur;
                cur = rear;
                index++;
            }
            if(curtail == null){
                curtail = last;
            }
            count++;
            if(count == size / k){
                if(prelast == null){
                    first.next = cur;
                }
                else{
                    prelast.next = last;
                    first.next = cur;
                }
                 
            }
            else{
                if(prelast != null){
                    prelast.next = last;
                    prelast = first;
                    pre = cur;
                } 
                else{
                    prelast = first;
                    pre = cur;
                }  
            } 
            
        }
        return curtail;
    }
}

递归法

class Solution {
    public ListNode reverseKGroup(ListNode head, int k) {
        ListNode prev = null;
        ListNode cur = head;
        ListNode next = null;
        ListNode check = head;
        int canProceed = 0;
        int count = 0;
        // 检查链表长度是否满足翻转
        while (canProceed < k && check != null) {
            check = check.next;
            canProceed++;
        }
        // 满足条件,进行翻转(关键)
        if (canProceed == k) {
            while (count < k && cur != null) {
                next = cur.next;
                cur.next = prev;
                prev = cur;
                cur = next;
                count++;
            }
            if (next != null) {
                // head 为链表翻转后的尾节点
                head.next = reverseKGroup(next, k);
            }
            // prev 为链表翻转后的头结点
            return prev;
        } else {
            // 不满住翻转条件,直接返回 head 即可
            return head;
        }
    }
}
LeetCode题号:96. 不同的二叉搜索树(中等)

若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值; 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值; 它的左、右子树也分别为二叉排序树。

class Solution{
    public List <TreeNote>generateTrees(int n)
    {
         if(n==0)
         return new ArrayList<>();
         return generateBST(1,n);
         }
     private List <TreeNode>generateBST(int left,int right)
     {
     List<TreeNode> res = new LinkedList<>();
     if (left > right) { 
     // 划分不到的时填null.
     res.add(null);
     return res;
     }
     for (int i = left; i <= right; i++)
      {                 
      List<TreeNode> leftTrees = generateBST(left, i - 1);            
      List<TreeNode> rightTrees = generateBST(i + 1, right);
      for (TreeNode leftTree : leftTrees)
       {                
                 for (TreeNode rightTree : rightTrees) { 
                  // 每个循环都要构造新的节点,不能在for 循环外面生成.
                            TreeNode root = new TreeNode(i);                    
                            root.left = leftTree;                    
                            root.right = rightTree;                    
                            res.add(root);
                            }
                      }
                }
                            return res;
           }
  }
LeetCode题号: 101. 对称二叉树(简单)

给定一个二叉树,检查它是否是镜像对称的。
例如,二叉树 [1,2,2,3,4,4,3] 是对称的。
1.左节点等于右节点
2.左节点的左子树等于右节点的右子树
3.左节点的右子树等有右节点的左子树

递归(害 没看懂)

class Solution {
public:
   bool isSymmetric(TreeNode* root) 
   {
     if(root==NULL)return 1;
     return judge(root->left,root->right);
   }
   int judge(TreeNode * root1,TreeNode *root2)
   {
   if(!root1&&!root2)return 1;
   else if(root1&&root2&&root1->val==root2->val&&judge(root1->left,root2->right)&&judge(root1->right,root2->left))return 1;
   else return 0;    
   }
 }
LeetCode题号: 99. 恢复二叉搜索树 (困难)

看到的解法

最后我想谈一些感想,对于链表我觉得蛮好用,可以解决很多问题,树我目前没有什么感想。感觉加入技术部的这后小一个月,分身乏术,没有太多的时间分配给技术任务的学习,可能是我效率太低,在班级事务,工图,微积分,C语言(张老师的实践训练好多TAT),信导的MATLAB之间周转,我很想每一样都兼顾,可是冥冥之中总有些东西抓也抓不住,我只能说尽力去做,不会的就找别人的CSDN看一看理解一下,能写就写,害。但期末可能task的质量不太高,毕竟学习为先

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值