leetcode 18 --- 4sum

1  题目

给出一个有n个元素的数组S,S中是否有元素a,b,c和d满足a+b+c+d=目标值?找出数组S中所有满足条件的四元组。

注意:

  1. 四元组(a、b、c、d)中的元素必须按非降序排列。(即a≤b≤c≤d)
  2. 解集中不能包含重复的四元组。
    例如:给出的数组 S = {1 0 -1 0 -2 2}, 目标值 = 0.↵↵    给出的解集应该是:↵    (-1,  0, 0, 1)↵    (-2, -1, 1, 2)↵    (-2,  0, 0, 2)

2  解法

2.1  我的第一版解法

写思路:

用循环的方法尝试所有的四个数组合。

我的第一版代码:

class Solution {
public:vector<vector<int> > fourSum(vector<int> &num, int target) {vector<vector<int> > res;if (num.size() < 4) {return res;}sort(num.begin(), num.end());for (int i = 0; i < num.size() - 3; i++) {for (int j = i + 1; j < num.size() - 2; j ++) {for (int k = j + 1; k < num.size() - 1; k ++) {for (int n = k + 1; n < num.size(); n ++) {if (num[i] + num[j] + num[k] + num[n] == target) {vector<int> tmp_res = {num[i], num[j], num[k], num[n]};res.push_back(tmp_res);}}}}}return res;}
};

结果发现过不了:

因为结果中有相同的数组:[-3,0,1,2],[-3,0,1,2],原因是有多个0实例,第一个[-3,0,1,2]用的一号0,第二个[-3,0,1,2]用的二号0.

2.2  我的第二版解法

思路:

因为先把数组从小到大排序完成了,所以相同的数只用第一个,用完之后执行检查直到下一个不一样的数。

代码:

class Solution {
public:vector<vector<int> > fourSum(vector<int> &num, int target) {vector<vector<int> > res;if (num.size() < 4) {return res;}sort(num.begin(), num.end());for (int i = 0; i < num.size() - 3;) {for (int j = i + 1; j < num.size() - 2;) {for (int k = j + 1; k < num.size() - 1;) {for (int n = k + 1; n < num.size();) {if (num[i] + num[j] + num[k] + num[n] == target) {vector<int> tmp_res = {num[i], num[j], num[k], num[n]};res.push_back(tmp_res);}while (++n < num.size() && num[n] == num[n - 1]){}}while (++k < num.size() - 1 && num[k] == num[k - 1]){}}while (++j < num.size() - 2 && num[j] == num[j - 1]){}}while (++i < num.size() - 3 && num[i] == num[i - 1]){}}return res;}
};

结果发现性能很差:

2.3  我的第三版解法

思路:

后来想出来一个点,因为这个数列是递增的,所以第一个数要不大于target的1/4,前两个数之和要不大于一半,前三个不大于3/4。

代码:

class Solution {
public:vector<vector<int> > fourSum(vector<int> &num, int target) {vector<vector<int> > res;if (num.size() < 4) {return res;}sort(num.begin(), num.end());for (int i = 0; i < num.size() - 3;) {if (num[i] * 4 > target)break;for (int j = i + 1; j < num.size() - 2;) {int sumij = num[i] + num[j];if (sumij * 2 > target)break;for (int k = j + 1; k < num.size() - 1;) {int sumijk = sumij + num[k];if (sumijk * 4 > target * 3)break;for (int n = k + 1; n < num.size();) {int sumijkn = sumijk + num[n];if (sumijkn > target)break;if (sumijk + num[n] == target) {vector<int> tmp_res = {num[i], num[j], num[k], num[n]};res.push_back(tmp_res);break;}while (++n < num.size() && num[n] == num[n - 1]){}}while (++k < num.size() - 1 && num[k] == num[k - 1]){}}while (++j < num.size() - 2 && num[j] == num[j - 1]){}}while (++i < num.size() - 3 && num[i] == num[i - 1]){}}return res;}
};

性能好了一些:

2.4  我的第四版解法

思路:

其实是看了讨论,发现最后两个数可以通过双指针查找。

代码:

class Solution {
public:vector<vector<int> > fourSum(vector<int> &num, int target) {vector<vector<int> > res;if (num.size() < 4) {return res;}sort(num.begin(), num.end());int n = num.size();for (int i = 0; i < n - 3;) {if (num[i] * 4 > target)break;for (int j = i + 1; j < n - 2;) {int sumij = num[i] + num[j];if (sumij * 2 > target)break;int l = j + 1;int r = n - 1;int target_sum = target - sumij;while (l < r) {int sumlr = num[l] + num[r];if (sumlr < target_sum) {while (++l < r && num[l] == num[l - 1]){}}if (sumlr == target_sum) {vector<int> tmp_res;tmp_res.push_back(num[i]);tmp_res.push_back(num[j]);tmp_res.push_back(num[l]);tmp_res.push_back(num[r]);res.push_back(tmp_res);while (++l < r && num[l] == num[l - 1]){}while (--r > l && num[r] == num[r + 1]){}}if (sumlr > target_sum) {while (--r > l && num[r] == num[r + 1]){}}}while (++j < num.size() - 2 && num[j] == num[j - 1]){}}while (++i < num.size() - 3 && num[i] == num[i - 1]){}}return res;}
};

最终性能还凑活:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/505468.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

leetcode 75 --- sort-colors

1 题目 现在有一个包含n个物体的数组&#xff0c;其中物体颜色为颜色为红色、白色或蓝色&#xff0c;请对这个数组进行排序&#xff0c;让相同颜色的物体相邻&#xff0c;颜色的顺序为红色&#xff0c;白色&#xff0c;蓝色。 我们用0,1,2分别代表颜色红&#xff0c;白&#…

leetcode 111 --- 二叉树最小深度

1 题目 求给定二叉树的最小深度。最小深度是指树的根结点到最近叶子结点的最短路径上结点的数量。 2 解法 2.1 递归方法 要找到最小深度,首先要确定有根到叶的第一个叶节点,也就是一层一层确定.所以有: /*** struct TreeNode {* int val;* struct TreeNode *left;* struct…

leetcode 145 --- 二叉树后序遍历

1 题目 用递归的方法对给定的二叉树进行后序遍历。 例如&#xff1a; 给定的二叉树为{1,#,2,3}, 返回[3,2,1]. 示例1 输入 {1,#,2,3} 输出 [3,2,1] 2 解法 2.1 递归解法 /*** struct TreeNode {* int val;* struct TreeNode *left;* struct TreeNode *right;* };*/c…

leetcode 144 --- 二叉树前序遍历

1 题目 求给定的二叉树的前序遍历。 2 解法 2.1 递归解法 2.2 非递归解法 前序遍历,先遍历根节点,然后遍历左节点,最后是右节点,所以用栈的方式,先是根节点入栈,然后出栈遍历,如果该节点有左右节点,那么左右节点入栈(应为右节点先入栈,然后是左节点,因为左节点先遍历,所以…

leetcode 116 --- 填充每个节点指向最右节点的next指针

1 题目 填充每个节点指向最右节点的next指针, 填充所有节点的next指针&#xff0c;指向最接近它的同一层右边节点。如果没有同一层没有右边的节点&#xff0c;则应该将next指针设置为NULL。 初始时&#xff0c;所有的next指针都为NULL 注意&#xff1a; 你只能使用常量级…

leetcode 110 --- 判断给定的二叉树是否是平衡二叉树

1 题目 判断给定的二叉树是否是平衡二叉树 平衡二叉树的性质为: 要么是一棵空树&#xff0c;要么任何一个节点的左右子树高度差的绝对值不超过 1。 一颗树的高度指的是树的根节点到所有节点的距离中的最大值。 2 解法 2.1 多次递归 最初的想法肯定是先求出每个节点的左右…

leetcode 109 --- 有序链表变成二叉搜索树

1 题目 给定一个单链表&#xff0c;其中的元素按升序排序&#xff0c;请将它转化成平衡二叉搜索树&#xff08;BST&#xff09; 2 解法 2.1 转化有序链表为数组 /*** struct TreeNode {* int val;* struct TreeNode *left;* struct TreeNode *right;* };*/ /*** struct Lis…

leetcode 112 --- 二叉树根节点到叶子节点和为指定值的路径

1 题目 给定一个二叉树和一个值sum&#xff0c;请找出所有的根节点到叶子节点的节点值之和等于sum 的路径. 2 解法 用递归的方法,如果当前不是叶子节点,就把sum减去当前的值,并把当前节点当作路径节点push进临时路径数组中,然后去检查其左右节点,如果是叶子节点的话,检查其值…

leetcode 107 --- 二叉树程序遍历 ii

1 题目 给定一个二叉树&#xff0c;返回该二叉树由底层到顶层的层序遍历&#xff0c;&#xff08;从左向右&#xff0c;从叶子节点到根节点&#xff0c;一层一层的遍历&#xff09; 2 解法 2.1 我的最初解法 按照正常的层序遍历应该是从上到下的,只要用一个栈先临时存一下每…

leetcode 148 --- 链表排序

1 题目 链表排序 2 解法 2.1 冒泡排序 /*** struct ListNode {* int val;* struct ListNode *next;* };*/class Solution { public:/*** * param head ListNode类 * return ListNode类*/ListNode* sortList(ListNode* head) {// write code hereif (head) {ListNode* endNo…

leetcode 3 --- 无重复字符的最长子串

1 题目 给定一个字符串&#xff0c;请你找出其中不含有重复字符的 最长子串 的长度。 2 思路 2.1 迭代思路 刚开始的想法肯定是暴力解法, 遍历字符串每一个字符, 看以当前字符为起点的最长无重复子串有多长, 这样做有一个可以优化的地方, 比如以当前循环到的字符起点A, 找到…

leetcode 1 --- 两数之和

1 题目 给定一个整数数组 nums 和一个目标值 target&#xff0c;请你在该数组中找出和为目标值的那 两个 整数&#xff0c;并返回他们的数组下标。 你可以假设每种输入只会对应一个答案。但是&#xff0c;数组中同一个元素不能使用两遍。 2 解法 struct haveOrigionIndexNu…

leetcode 2 --- 两数相加

1 题目 给出两个 非空 的链表用来表示两个非负的整数。其中&#xff0c;它们各自的位数是按照 逆序 的方式存储的&#xff0c;并且它们的每个节点只能存储 一位 数字。 如果&#xff0c;我们将这两个数相加起来&#xff0c;则会返回一个新的链表来表示它们的和。 您可以假设…

leetcode 9 --- 回文数

1 题目 判断一个整数是否是回文数。回文数是指正序&#xff08;从左向右&#xff09;和倒序&#xff08;从右向左&#xff09;读都是一样的整数。 2 解法 2.1 初版 2.1.1 思路 由于题目不允许把数直接转化为字符串, 所以想到了把数的每一位转换为双向数组, 然后对头尾一点…

C++中类和对象的一些注意事项

1. struct和class的区别 默认的访问权限不同, struct默认访问权限是public, 而class的默认访问权限是private. 2. 构造析构函数 2.1 注意事项 匿名构造函数在当前行结束后, 系统会立即释放其内存占用.不要用匿名拷贝构造函数.创建一个类之后, 编译器会自动创建三个函数, 默…

C++中类和对象的一些注意事项 ---继承

1 继承中的访问权限问题 所有继承方式, 子类都无法访问父类的private成员. 那么用如下测试代码尝试一下: #include <iostream> using namespace std;class father { public:int m_father_public_value; protected:int m_father_protected_value; private:int m_father_…

C++中类和对象的一些注意事项 --- 多态

1. 一些继承中的问题 1.1 多继承中父类含有重名成员问题 如下: #include <iostream> #include <string> using namespace std;class father1 { public:father1() {class_name "father1";}string class_name; };class father2 { public:father2() {cl…

电脑按f8无法进入安全模式_自已有电脑的人,都会遇到系统死机问题,教大家实用一招自已解决...

其实我们电脑死机蓝屏重启并不可怕&#xff0c;如果只要懂得最基本的一些查找方法就可以解决这些问题&#xff0c;因为电脑是一个完整的系统&#xff0c;既然是系统工程必须由硬件与软件共同合作才能完成出色的任务&#xff0c;如果电脑出现死机蓝屏等问题可以参考以下方式进行…

台式电脑键盘字母乱了_键盘侠的育儿经利用键盘引导学龄前儿童正确使用电脑、学习英文字母和拼音...

点击上方“总想做自己”关注我可以订阅哦一点资讯邀约作者&#xff1a;方游专注探讨个人成长与正向激励的话题&#xff0c;有干货&#xff0c;不再错过&#xff0c;快来点击关注吧&#xff01;微信公众号&#xff1a;apple_seeworld难得机会与孩子在家里有长达半月的相处&#…

C++模板的注意事项

函数模板 template <typename T> //把typename换成class也可以 函数模板调用方法 使用过程中, 有两种方法调用, 如下: 自动类型推导:#include <iostream>template <class T> void swap(T &first, T &second) {T temp;temp first;first se…