数据结构刷题记录--编程题

1(链表)
在这里插入图片描述
解析:我们可以修改给定节点之前的指针,使它指向该节点的下一个节点,但是我们无法访问该节点之前的位置,无法修改,所以我们需要将该节点的数据更改为后面节点的数据,然后删除该节点后面的节点,如果要删除的节点是末尾节点,则不能这样做

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public void deleteNode(ListNode node) {
        node.val = node.next.val;					//更改该节点的值=后面节点的值
        node.next = node.next.next;				//使该节点直接指向后面的节点后面的节点
    }
}

2.(链表)
在这里插入图片描述
解析:我们需要定义一个新的指针指向第一个节点的前一个位置赋值为空,使用循环将后一个节点指向前一个节点,并将两个节点的指针后移,当当前指针指向空时,循环结束。

class Solution {
    public ListNode reverseList(ListNode head) {
        ListNode pre = null;        //当前节点的上一个节点,初始为空
        ListNode cur = head;        //当前节点,初始为头结点
        while(cur != null){
            ListNode temp = cur.next;     //代表当前节点的下一个节点,用来将当前节点指针后移  
            cur.next = pre;               //使当前节点指向前一个节点
            pre = cur;                    //前一个节点指针后移
            cur = temp;                   //当前节点指针后移
        }
        return pre;
    }
}

3.(链表)
在这里插入图片描述
解析:使用快慢指针法,定义两个指针,慢指针初始位置为head,快指针初始位置为head.next,设置循环,快指针后移的速度是慢指针的两倍,如果快指针和慢指针相遇,则有环形;如果快指针最终指向null,则没有环形

public class Solution {
    public boolean hasCycle(ListNode head) {
        if(head == null||head.next== null){
            return false;								//判定链表中如果没有元素或只有一个
        }
        ListNode a = head;						//定义慢指针
        ListNode b = head.next;				//定义快指针
        while(a != b){
            if(b == null||b.next == null){
                return false;							//快指针最终指向null,返回false
            }
            a = a.next;								//慢指针速度后移一次
            b = b.next.next;						//快指针后移两次
        }	
        return true;									//快慢指针相遇,循环结束,返回true
    }
}

4.删除链表中的元素(链表)在这里插入图片描述
解析:找一个数据不是val的节点为头结点,定义两个指针指向该节点,一个进行删除操作,另一个进行查找操作,如果查找节点指向要删除的节点,则删除节点直接跳过该节点指向下一个节点

class Solution {
     public ListNode removeElements(ListNode head, int val) {
        while (head != null) {                  //找到一个节点作为头结点
            if (head.val != val)
                break;
            head = head.next;
        }
        ListNode pre = head;                    //删除指针
        ListNode cur = head;                    //查找指针
        while (cur != null) {
            if (cur.val == val){                 
                pre.next = cur.next;            //如果查找到元素,则使删除节点指向该节点的下一个节点
            }else{
                pre = cur;                      //否则使这两个节点指向同一个节点
            }
            cur = cur.next;                     //查找节点后移查找
        }
        return head;
    }
}

5.链表的中间节点(链表)
在这里插入图片描述
解析:我们可以将链表转换为一个数组,然后中间节点就是【length/2】

class Solution {
    public ListNode middleNode(ListNode head) {
        ListNode [] arr = new LisNode(100);						//创建一个长度为100的存储节点的数组
        int i = 0;
        while (head.next != null){
        	arr[i++] = head;
        	head = head.next;											//遍历链表存在数组中
        }
        return arr[i/2];														//返回数组的中间元素
    }
}

6.反转二维数组(数组)
在这里插入图片描述
解析:可以将每行数组从后往前遍历,然后用1减去每个元素,再返回

class Solution {
    public int[][] flipAndInvertImage(int[][] A) {
        int x=A.length;
        int y=A[0].length;
        int[][] B = new int[x][y];
        for (int i=0;i<x;i++){
            for (int j=0;j<y;j++){
                B[i][y-j-1]=1-A[i][j];   //从后往前赋值,同时取反
            }
        }
        return B;
    }
}

7.高度检查器(数组)
在这里插入图片描述
解析:可以将原数组先复制一份出来,然后将新数组按升序排好序,最后将原数组与新数组进行比较,得出元素不同的个数

class Solution {
    public int heightChecker(int[] heights) {
        int[] arr = heights.clone();                //将原数组复制一份
        int temp;
        for(int i=0;i<arr.length;i++){              //将新数组用选择排序的方法升序排序
            for(int j=i+1;j<arr.length;j++){
               if(arr[i]>arr[j]){
                 temp=arr[i];
                 arr[i]=arr[j];
                 arr[j]=temp;
                }
            }
        }
        int diff = 0;
        for (int i=0; i<heights.length; i++) {          //将新数组与原数组进行比较
            if (arr[i] != heights[i]) {
                diff++;
            }
        }
        return diff;
    }
}

8.二叉搜索树的范围和(二叉树)
在这里插入图片描述
解析:题目要求求出范围在L和R之间的所有元素之和,我们需要对树进行深度优先遍历,从根节点开始,如果节点元素在L和R之间,则进行自加操作,如果元素大于L,则向右子树进行搜索,如果节点元素小于R,则向左子树进行搜索,当节点为null时递归结束

class Solution {
    int sum = 0;				//定义和默认值为0
    public int rangeSumBST(TreeNode root, int L, int R) {
        add(root,L,R);	
        return sum;
    }
    
    public void add(TreeNode p,int L,int R){
        if(p != null){
            if(p.val>=L&&p.val<=R){
                sum += p.val;
            }if(p.val>L){
                add(p.left,L,R);
            }if(p.val<R){
                add(p.right,L,R);
            }
        }
    }
}

9.反转二叉树(二叉树)
在这里插入图片描述
解析:使用递归将每个节点的孩子节点直接互换,最后返回

class Solution {
    public TreeNode invertTree(TreeNode root) {
        if(root == null){
            return root;
        }
        TreeNode right = invertTree(root.right);
        TreeNode left = invertTree(root.left);
        root.left = right;
        root.right = left;
        return root;
    }
}

10.从二叉搜索树到更大和树(二叉树)
在这里插入图片描述
解析:题目要将每个节点的数据改为该节点元素加上所有大于该元素的和,由二叉搜索树的性质可知,节点右边的所有元素都大于该节点元素,所以使用反转的中序遍历将节点右边元素相加重新赋值给该节点即可

class Solution {
    public TreeNode bstToGst(TreeNode root) {
        dfs(root);
        return root;
    }
    
    int sum = 0;// 记录每个节点的右边的所有节点和,即原树中大于 node.val 的值之和
    private void dfs(TreeNode root) {
        if (root == null) {
            return;
        }
        
        dfs(root.right);// 先访问所有大于root的节点
        root.val += sum;// 赋值给当前节点
        sum = root.val;// 保存更大和
        dfs(root.left);// 后访问小于root的节点
    }
}

11.对称二叉树(二叉搜索树)
在这里插入图片描述
解析:当一个树二叉树左子树的根节点元素等于右子树的根节点元素,并且每个子树的右子树都与另一个树的左子树对称,则这个二叉树对称

class Solution {
    public boolean isSymmetric(TreeNode root) {
        return add(root,root);
    }
    
    public boolean add(TreeNode t1,TreeNode t2){
        if(t1==null&&t2==null){
            return true;
        }
        if(t1==null||t2==null){
            return  false;
        }
        return (t1.val==t2.val&&add(t1.right,t2.left)&&add(t1.left,t2.right));
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
对于计算机专业的学生而言,参加各类比赛能够带来多方面的益处,具体包括但不限于以下几点: 技能提升: 参与比赛促使学生深入学习和掌握计算机领域的专业知识与技能,如编程语言、算法设计、软件工程、网络安全等。 比赛通常涉及实际问题的解决,有助于将理论知识应用于实践中,增强问题解决能力。 实践经验: 大多数比赛都要求参赛者设计并实现解决方案,这提供了宝贵的动手操作机会,有助于积累项目经验。 实践经验对于计算机专业的学生尤为重要,因为雇主往往更青睐有实际项目背景的候选人。 团队合作: 许多比赛鼓励团队协作,这有助于培养学生的团队精神、沟通技巧和领导能力。 团队合作还能促进学生之间的知识共享和思维碰撞,有助于形成更全面的解决方案。 职业发展: 获奖经历可以显著增强简历的吸引力,为求职或继续深造提供有力支持。 某些比赛可能直接与企业合作,提供实习、工作机会或奖学金,为学生的职业生涯打开更多门路。 网络拓展: 比赛是结识同行业人才的好机会,可以帮助学生建立行业联系,这对于未来的职业发展非常重要。 奖金与荣誉: 许多比赛提供奖金或奖品,这不仅能给予学生经济上的奖励,还能增强其成就感和自信心。 荣誉证书或奖状可以证明学生的成就,对个人品牌建设有积极作用。 创新与研究: 参加比赛可以激发学生的创新思维,推动科研项目的开展,有时甚至能促成学术论文的发表。 个人成长: 在准备和参加比赛的过程中,学生将面临压力与挑战,这有助于培养良好的心理素质和抗压能力。 自我挑战和克服困难的经历对个人成长有着深远的影响。 综上所述,参加计算机领域的比赛对于学生来说是一个全面发展的平台,不仅可以提升专业技能,还能增强团队协作、沟通、解决问题的能力,并为未来的职业生涯奠定坚实的基础。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值