LeetCode C++刷题133-137题题解

目录

 

133、克隆图

题目

题解

代码

134、加油站

题目

题解

代码

135、分发糖果

题目

题解

代码

136、只出现一次的数字

题目

题解

代码

137、只出现一次的数字II

题目

题解

代码


133、克隆图

题目

给你无向 连通 图中一个节点的引用,请你返回该图的 深拷贝(克隆)。

图中的每个节点都包含它的值 val(int) 和其邻居的列表(list[Node])。

class Node {
    public int val;
    public List<Node> neighbors;
}
 

测试用例格式:

简单起见,每个节点的值都和它的索引相同。例如,第一个节点值为 1(val = 1),第二个节点值为 2(val = 2),以此类推。该图在测试用例中使用邻接列表表示。

邻接列表 是用于表示有限图的无序列表的集合。每个列表都描述了图中节点的邻居集。

给定节点将始终是图中的第一个节点(值为 1)。你必须将 给定节点的拷贝 作为对克隆图的引用返回。

 

示例 1:

输入:adjList = [[2,4],[1,3],[2,4],[1,3]]
输出:[[2,4],[1,3],[2,4],[1,3]]
解释:
图中有 4 个节点。
节点 1 的值是 1,它有两个邻居:节点 2 和 4 。
节点 2 的值是 2,它有两个邻居:节点 1 和 3 。
节点 3 的值是 3,它有两个邻居:节点 2 和 4 。
节点 4 的值是 4,它有两个邻居:节点 1 和 3 。
示例 2:

输入:adjList = [[]]
输出:[[]]
解释:输入包含一个空列表。该图仅仅只有一个值为 1 的节点,它没有任何邻居。
示例 3:

输入:adjList = []
输出:[]
解释:这个图是空的,它不含任何节点。
示例 4:

输入:adjList = [[2],[1]]
输出:[[2],[1]]
 

提示:

节点数不超过 100 。
每个节点值 Node.val 都是唯一的,1 <= Node.val <= 100。
无向图是一个简单图,这意味着图中没有重复的边,也没有自环。
由于图是无向的,如果节点 p 是节点 q 的邻居,那么节点 q 也必须是节点 p 的邻居。
图是连通图,你可以从给定节点访问到所有节点。
通过次数47,496提交次数73,278
在真实的面试中遇到过这道题?


来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/clone-graph
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

题解

方法一:深度优先搜索

方法二:广度优先搜索

代码

/*
// Definition for a Node.
class Node {
public:
    int val;
    vector<Node*> neighbors;
    
    Node() {
        val = 0;
        neighbors = vector<Node*>();
    }
    
    Node(int _val) {
        val = _val;
        neighbors = vector<Node*>();
    }
    
    Node(int _val, vector<Node*> _neighbors) {
        val = _val;
        neighbors = _neighbors;
    }
};
*/

class Solution {
public:
    // 深度优先搜索
//     Node* cloneGraph(Node* node) 
//     {
//         if(node == nullptr) {
//             return nullptr;
//         }
//         if(m.find(node) != m.end()) {
//             return m[node];
//         }
//         Node *newNode = new Node(node->val);
//         m[node] = newNode;
//         for(int i = 0; i <(node->neighbors).size(); ++i) {
//             Node *neighbor_node = cloneGraph(node->neighbors[i]);;
//             m[node]->neighbors.push_back(neighbor_node);
//         }
//         return m[node];
//     }
// private:
//      unordered_map<Node*, Node*> m;

// 广度优先搜索
    Node* cloneGraph(Node* node) 
    {
        if(node == nullptr) {
            return nullptr;
        }

        Node *newNode = new Node(node->val);
        
        unordered_map<Node*, Node*> m;
        m[node] = newNode;
        queue<Node*> que;
        que.push(node);

        while(!que.empty()) {
            Node* n = que.front();
            que.pop();
            for(Node *neighbor: n->neighbors) {
                if(m.find(neighbor) == m.end()) {
                    que.push(neighbor);
                    m[neighbor] = new Node(neighbor->val);
                }
                m[n]->neighbors.emplace_back(m[neighbor]);
            }
        }

        return m[node];
    }
//     //广度优先遍历
//     /*
//     Node* cloneGraph(Node* node) 
//     {
//         //若传入的node为空指针,则返回空
//         if(node == nullptr) {
//             return nullptr;
//         }
//         Node *newNode = new Node(node->val);

//         unordered_map<Node*, Node*> m;
//         m[node] = newNode;

//         queue<Node*> que;
//         que.push(node);
//         //当队列不为空时
//         while(!que.empty()) {
//             Node *n = que.front();
//             que.pop();
//             for(Node *neighbor: n->neighbors) {
//                 if(m.find(neighbor) == m.end()) {
//                     que.push(neighbor);
//                     m[neighbor] = new Node(neighbor->val);
//                 }
//                 m[n]->neighbors.emplace_back(m[neighbor]);
//             }
//         }

//         return m[node];
//     }
//     */
//     //深度优先遍历
// private:
//     unordered_map<Node*, Node*> m;
// public:
//     Node* cloneGraph(Node* node) 
//     {
//          if(node == nullptr) {
//             return nullptr;
//         }
//         if(m.find(node) != m.end()) {
//             return m[node];
//         }
//         Node *newNode = new Node(node->val);
//         m[node] = newNode;

//         for(Node *neighbor: node->neighbors) {
//             m[node]->neighbors.emplace_back(cloneGraph(neighbor));
//         }

//         return m[node];
//     }
};

134、加油站

题目

在一条环路上有 N 个加油站,其中第 i 个加油站有汽油 gas[i] 升。

你有一辆油箱容量无限的的汽车,从第 i 个加油站开往第 i+1 个加油站需要消耗汽油 cost[i] 升。你从其中的一个加油站出发,开始时油箱为空。

如果你可以绕环路行驶一周,则返回出发时加油站的编号,否则返回 -1。

说明: 

如果题目有解,该答案即为唯一答案。
输入数组均为非空数组,且长度相同。
输入数组中的元素均为非负数。
示例 1:

输入: 
gas  = [1,2,3,4,5]
cost = [3,4,5,1,2]

输出: 3

解释:
从 3 号加油站(索引为 3 处)出发,可获得 4 升汽油。此时油箱有 = 0 + 4 = 4 升汽油
开往 4 号加油站,此时油箱有 4 - 1 + 5 = 8 升汽油
开往 0 号加油站,此时油箱有 8 - 2 + 1 = 7 升汽油
开往 1 号加油站,此时油箱有 7 - 3 + 2 = 6 升汽油
开往 2 号加油站,此时油箱有 6 - 4 + 3 = 5 升汽油
开往 3 号加油站,你需要消耗 5 升汽油,正好足够你返回到 3 号加油站。
因此,3 可为起始索引。
示例 2:

输入: 
gas  = [2,3,4]
cost = [3,4,3]

输出: -1

解释:
你不能从 0 号或 1 号加油站出发,因为没有足够的汽油可以让你行驶到下一个加油站。
我们从 2 号加油站出发,可以获得 4 升汽油。 此时油箱有 = 0 + 4 = 4 升汽油
开往 0 号加油站,此时油箱有 4 - 3 + 2 = 3 升汽油
开往 1 号加油站,此时油箱有 3 - 3 + 3 = 3 升汽油
你无法返回 2 号加油站,因为返程需要消耗 4 升汽油,但是你的油箱只有 3 升汽油。
因此,无论怎样,你都不可能绕环路行驶一周。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/gas-station
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

题解

方法一:暴力法

方法二:一次遍历

代码

class Solution {
public:
    int canCompleteCircuit(vector<int>& gas, vector<int>& cost) {
        // 方法一:暴力法
        // int n = gas.size();
        // for(int i = 0; i < n * 2; i++) {
        //     int count = 0;
        //     int j = i;
        //     int sum = 0;
        //     while(j < n * 2 && (sum = sum + gas[j % n]) >= cost[j % n]) {
        //         sum -= cost[j % n];
        //         j++;
        //         count++;
        //         if(count == n + 1) {
        //             return i;
        //         }
        //     }
        // }

        // return -1;
        int total = 0, current = 0;
        int start_position = 0;
        for(int i = 0; i < gas.size(); ++i) {
            total += gas[i] - cost[i];
            current += gas[i] - cost[i];

            if(current < 0) {
                start_position = i + 1;
                current = 0;
            }
        }
        return total >= 0 ? start_position : -1;
    }
};

135、分发糖果

题目

老师想给孩子们分发糖果,有 N 个孩子站成了一条直线,老师会根据每个孩子的表现,预先给他们评分。

你需要按照以下要求,帮助老师给这些孩子分发糖果:

每个孩子至少分配到 1 个糖果。
相邻的孩子中,评分高的孩子必须获得更多的糖果。
那么这样下来,老师至少需要准备多少颗糖果呢?

示例 1:

输入: [1,0,2]
输出: 5
解释: 你可以分别给这三个孩子分发 2、1、2 颗糖果。
示例 2:

输入: [1,2,2]
输出: 4
解释: 你可以分别给这三个孩子分发 1、2、1 颗糖果。
     第三个孩子只得到 1 颗糖果,这已满足上述两个条件。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/candy
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

题解

两次扫描

代码

class Solution {
public:
    int candy(vector<int>& ratings) {
        int n = ratings.size();
        vector<int> left_candy(n, 1);
        vector<int> right_candy(n, 1);
        
        for(int i = 1; i < n; i++) {
            if(ratings[i] > ratings[i - 1]) {
                left_candy[i] = left_candy[i - 1] + 1;
            }
        }

        for(int j = n - 2; j >= 0; j--) {
            if(ratings[j] > ratings[j + 1]) {
                right_candy[j] = right_candy[j + 1] + 1;
            }
        }

        int sum = 0;
        for(int k = 0; k < n; k++) {
            sum += max(left_candy[k], right_candy[k]);
        }
        return sum;
    }
};

136、只出现一次的数字

题目

给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。

说明:

你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗?

示例 1:

输入: [2,2,1]
输出: 1
示例 2:

输入: [4,1,2,1,2]
输出: 4

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/single-number
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

题解

异或

代码

class Solution {
public:
    int singleNumber(vector<int>& nums) {
       // 交换律:a ^ b ^ c <=> a ^ c ^ b
       // 任何数与0异或为任何数 0 ^ n => n
       // 相同的数异或为0: n ^ n => 0
       int result = 0;
       for(int num: nums) {
           result = result ^ num;
       } 
       return result;
    }
};

137、只出现一次的数字II

题目

给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现了三次。找出那个只出现了一次的元素。

说明:

你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗?

示例 1:

输入: [2,2,3,2]
输出: 3
示例 2:

输入: [0,1,0,1,0,1,99]

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/single-number-ii
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

题解

异或

代码

class Solution {
public:
    int singleNumber(vector<int>& nums) {
        /*
        0 ^ x = x,
        x ^ x = 0;
        x & ~x = 0,
        x & ~0 =x
        */
        int a = 0;
        int b = 0;
        for(int num: nums) {
            b = (b ^ num) & (~a);
            a = (a ^ num) &(~b);
        }
        return b;
    }
};

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

cchangcs

谢谢你的支持~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值