剑指offer30天打卡活动(day12 - day15)

目录

day12:

剑指 Offer 25. 合并两个排序的链表

剑指 Offer 52. 两个链表的第一个公共节点

day13:

剑指 Offer 21. 调整数组顺序使奇数位于偶数前面

剑指 Offer 57. 和为 s 的两个数字

剑指 Offer 58 - I. 翻转单词顺序 

day14:

剑指 Offer 12. 矩阵中的路径

剑指 Offer 13. 机器人的运动范围

day15:

剑指 Offer 34. 二叉树中和为某一值的路径

剑指 Offer 36. 二叉搜索树与双向链表

剑指 Offer 54. 二叉搜索树的第 k 大节点


day12:

一. 剑指 Offer 25. 合并两个排序的链表

题目:

输入两个递增排序的链表,合并这两个链表并使新链表中的节点仍然是递增排序的。

示例:

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

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

解题思路: 

双指针

C++代码:

/**
 * 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 = new ListNode(0);
        ListNode* res = temp;

        while(l1 != nullptr && l2 != nullptr){
            if(l1 -> val <= l2 -> val){
                res -> next = l1;
                l1 = l1 -> next;
            }else{
                res -> next = l2;
                l2 = l2 -> next;
            }
            res = res -> next;
        }

        if(l1 == nullptr)
            res -> next = l2;
        else
            res -> next = l1;

        return temp -> next;
    }
};

二. 剑指 Offer 52. 两个链表的第一个公共节点

题目:

输入两个链表,找出它们的第一个公共节点。

示例:

输入: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 个节点。

解题思路: 

双指针

C++代码:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        ListNode* A = headA, *B = headB;
        while(A != B)
        {
            if(A != nullptr)
                A = A -> next;
            else
                A = headB;
            
            if(B != nullptr)
                B = B -> next;
            else
                B = headA;
        }

        return A;
    }
};

day13:

一. 剑指 Offer 21. 调整数组顺序使奇数位于偶数前面

题目:

输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有奇数在数组的前半部分,所有偶数在数组的后半部分。

示例:

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

解题思路: 

双指针

C++代码:

class Solution {
public:
    vector<int> exchange(vector<int>& nums) {
        int i = 0, j = nums.size() - 1;
        while(i < j)
        {
            while(i < j && nums[i] % 2 != 0) i++;
            while(i < j && nums[j] % 2 == 0) j--;
            swap(nums[i], nums[j]);
        }
        return nums;
    }
};

二.  剑指 Offer 57. 和为 s 的两个数字

题目:

输入一个递增排序的数组和一个数字s,在数组中查找两个数,使得它们的和正好是s。如果有多对数字的和等于s,则输出任意一对即可。

示例:

输入:nums = [2,7,11,15], target = 9
输出:[2,7] 或者 [7,2]

解题思路: 

双指针

C++代码:

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        int i = 0, j = nums.size() - 1;
        while(i < j)
        {
            if(nums[i] + nums[j] > target) j--;
            else if(nums[i] + nums[j] < target) i++;
            else return {nums[i], nums[j]};
        }
        return {};
    }
};

三. 剑指 Offer 58 - I. 翻转单词顺序 

题目:

输入一个英文句子,翻转句子中单词的顺序,但单词内字符的顺序不变。为简单起见,标点符号和普通字母一样处理。例如输入字符串"I am a student. ",则输出"student. a am I"。

示例:

输入:"the sky is blue"
输出:"blue is sky the"

解题思路: 

双指针

C++代码:

class Solution {
public:
    string reverseWords(string s) {
        int i = s.size() -1, j = s.size() - 1;
        string temp;
        while(i >= 0 && j >= 0)
        {
            if(s[i] == ' ')
            {
                i--;
                continue;
            }
            j = i;
            while(i >= 0 && s[i] != ' ') i--;
            temp += s.substr(i+1, j - i) + ' ';
        }
        temp.back() = '\0';
        return temp;
    }
};

day14:

一. 剑指 Offer 12. 矩阵中的路径

题目:

给定一个 m x n 二维字符网格 board 和一个字符串单词 word 。如果 word 存在于网格中,返回 true ;否则,返回 false 。单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用。

示例:

输入:board = [ ["A", "B", "C", "E"], ["S", "F", "C", "S"], ["A", "D", "E", "E"]]

           word = "ABCCED"


输出:true

解题思路: 

递归

C++代码:

class Solution {
public:
    bool exist(vector<vector<char>>& board, string word) {
        for(int i = 0; i < board.size(); i++)
        {
            for(int j = 0; j < board[0].size(); j++)
            {
                if(dfs(board, word, i , j, 0)) return true;
            }
        }
            
        return false;
    }
private:
    bool dfs(vector<vector<char>> &board, string word, int i , int j, int k)
    {
        if(i >= board.size() || j >= board[0].size() || i < 0 || j < 0 || board[i][j] != word[k])
            return false;
        
        if(k == word.size() - 1) return true;
        board[i][j] = '\0';
        bool res = dfs(board, word, i-1, j, k+1) || dfs(board, word, i, j-1, k+1)
                || dfs(board, word, i+1, j, k+1) || dfs(board, word, i, j+1, k+1);

        board[i][j] = word[k];
        return res;
    }

};

二. 剑指 Offer 13. 机器人的运动范围

题目:

地上有一个m行n列的方格,从坐标 [0,0] 到坐标 [m-1,n-1] 。一个机器人从坐标 [0, 0] 的格子开始移动,它每次可以向左、右、上、下移动一格(不能移动到方格外),也不能进入行坐标和列坐标的数位之和大于k的格子。例如,当k为18时,机器人能够进入方格 [35, 37] ,因为3+5+3+7=18。但它不能进入方格 [35, 38],因为3+5+3+8=19。请问该机器人能够到达多少个格子?

示例:

输入:m = 2, n = 3, k = 1


输出:3

解题思路: 

递归

C++代码:

class Solution {
public:
    int movingCount(int m, int n, int k) {
        vector<int> temp(n, 0);
        vector<vector<int>> mark;
        for(int i = 0; i < m; i++)
        {
            mark.push_back(temp);
        }
        return dfs(0, 0, m, n, k, mark);
    }

private:
    int dfs(int i, int j, int m, int n, int k, vector<vector<int>> &mark)
    {
        if(i < 0 || j < 0 || i >= m || j >= n || mark[i][j] != 0 || i%10 + i/10 + j%10 + j/10 > k)
            return 0;

        mark[i][j] = 1;
        int res = 1 + dfs(i+1, j, m, n, k, mark) + dfs(i, j+1, m, n, k, mark)
                    + dfs(i-1, j, m, n, k, mark) + dfs(i, j-1, m, n, k, mark);
        
        return res;
    }
};

day15:

一. 剑指 Offer 34. 二叉树中和为某一值的路径

题目:

给你二叉树的根节点 root 和一个整数目标和 targetSum ,找出所有 从根节点到叶子节点 路径总和等于给定目标和的路径。

叶子节点 是指没有子节点的节点。

示例:

输入:root = [5, 4, 8, 11, null, 13, 4, 7, 2, null, null, 5, 1], targetSum = 22


输出:[[5, 4, 11, 2], [5, 8, 4, 5]]

解题思路: 

递归

C++代码:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    vector<vector<int>> pathSum(TreeNode* root, int target) {
        dfs(root, target);
        return res;
    }

private:
    vector<vector<int>> res;
    vector<int> temp;
    void dfs(TreeNode* root, int target){
        if(root == nullptr) return;
        temp.push_back(root -> val);
        target -= root -> val;
        if(target == 0 && root -> left == nullptr && root -> right == nullptr)
            res.push_back(temp);
        dfs(root -> left, target);
        dfs(root -> right, target);
        temp.pop_back();
    }
};

二. 剑指 Offer 36. 二叉搜索树与双向链表

题目:

输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的循环双向链表。要求不能创建任何新的节点,只能调整树中节点指针的指向。

C++代码:

/*
// Definition for a Node.
class Node {
public:
    int val;
    Node* left;
    Node* right;

    Node() {}

    Node(int _val) {
        val = _val;
        left = NULL;
        right = NULL;
    }

    Node(int _val, Node* _left, Node* _right) {
        val = _val;
        left = _left;
        right = _right;
    }
};
*/
class Solution {
public:
    Node* treeToDoublyList(Node* root) {       
        if(root == nullptr) return nullptr;
        dfs(root);
        pre -> right = head;
        head -> left = pre;
        return head;
        
    }

private:
    Node* pre, *head;
    void dfs(Node* cur){
        if(cur == nullptr) return ;
        dfs(cur -> left);
        if(pre != nullptr) pre -> right = cur;
        else head = cur;
        cur -> left = pre;
        pre = cur;
        dfs(cur -> right);
    }

};

三. 剑指 Offer 54. 二叉搜索树的第 k 大节点

题目:

给定一棵二叉搜索树,请找出其中第 k 大的节点的值。

示例:

输入:root = [3, 1, 4, null, 2], k = 1


输出:4

解题思路: 

递归

C++代码:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    int kthLargest(TreeNode* root, int k) {
        int res;
        dfs(root, k, res);
        return res;

    }

private:
    void dfs(TreeNode* root, int &k, int &res){
        if(root == nullptr) return ;
        dfs(root -> right, k, res);
        if(k == 0) return ;
        k--;
        if(k == 0) res = root -> val;
        dfs(root -> left, k, res);
    }
};

 题目源自:

leetcode图解算法数据结构

  • 22
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值