算法day7

454. 四数相加 II

给你四个整数数组 nums1、nums2、nums3 和 nums4 ,数组长度都是 n ,请你计算有多少个元组 (i, j, k, l) 能满足:

0 <= i, j, k, l < n

nums1[i] + nums2[j] + nums3[k] + nums4[l] == 0

解法:创建一个map用于存放数组1,2的和,即key,以及和出现的次数,即value;再遍历数组1,2,将和对应的位置进行计数;再遍历数组3,4,在map中查找是否存在等于和为0的数,即数组3,4的和的负数;如果key存在,则返回map中对应的value,即这个数出现的次数

class Solution {
public:
    int fourSumCount(vector<int>& nums1, vector<int>& nums2, vector<int>& nums3, vector<int>& nums4) {
        //定义一个mao表,用于存放数组nums1,nums2的和
        unordered_map<int,int> map;
        //遍历数组nums1,nums2,记录他们的和,并存入map表中
        //在map表中,key是他们的和。value是和出现的次数
        for(int a:nums1)
        {
            for(int b:nums2)
            {
                map[a+b]++;
            }
        }
        int sum=0; //定义一个计数,统计和为0的个数
        //遍历数组nums3,nums4
        for(int c:nums3)
        {
            for(int d:nums4)
            {
                //如果在map中能找到0-(c+d)的值,就表示在nums1,nums2数组的和中存在与数组nums3,nums4的和为0的key
                if(map.find(0-(c+d))!=map.end())
                {
                    //在nums1,nums2的和中找到key,则返回key的value,即nums1,nums2的和出现的次数
                    sum+=map[0-(c+d)];
                }
            }
        }
        return sum; //返回满足和为0的个数
    }
};
15. 三数之和

给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != j、i != k 且 j != k ,同时还满足 nums[i] + nums[j] + nums[k] == 0 。请

你返回所有和为 0 且不重复的三元组。

注意:答案中不可以包含重复的三元组。

解法:双指针解法

先对数组进行快速排序,sort(nums.begin(),nums.end()),从小到大排序;

三个元素,一个当前数组元素的下标,一个左指针(当前元素的下一个元素的下标),一个右指针(数组的最后一个元素的下标);

当三个元素之和大于0时,表示和过大,因为数组是排序过的,所以应该右指针向前移动一位,让右指针的元素的值减小,使得和减小;当三个元素之和小于0时,表示和过小,所以应该左指针向后移动一位,让左指针的元素的值增加,使得和增加;如果等于0,则写入二维数组result.push_back(vector<int>{a,b,c}),同时双指针收缩

class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
        //创建一个二维数组
        vector<vector<int>> result;
        //快速排序,让数组从小到大排序
        sort(nums.begin(),nums.end());
        //遍历数组,i为当前数组下标
        for(int i=0;i<nums.size();i++)
        {
            //如果排序后的数组第一个元素大于零,则不存在a+b+c等于0的情况了,就直接返回结果
            if(nums[i]>0)
            {
                return result;
            }
            //去重,如果当前元素等于前一个元素,则跳出当前循环,继续下一个循环
            if(i>0 && nums[i]==nums[i-1])
            {
                continue;
            }
            //左指针等于当前数组下标的下一个下标
            int left=i+1;
            //右指针等于数组最后一个元素的下标
            int right=nums.size()-1;
            //当左右指针不相等时
            while(right>left)
            {
                //如果a+b+c大于0,则表示和太大了,所以右指针向前移动一位,让数组之和减小
                if(nums[i]+nums[left]+nums[right]>0)
                {
                    right--;
                }
                //如果a+b+c小于0,则表示和太小了,所以左指针向后移动一位,让数组之和增加
                else if(nums[i]+nums[left]+nums[right]<0)
                {
                    left++;
                }
                else //如果等于0
                {
                    //将当前的数组元素写入二维数组中
                    result.push_back(vector<int>{nums[i],nums[left],nums[right]});
                    // 去重逻辑应该放在找到一个三元组之后,对b 和 c去重
                    while (right > left && nums[right] == nums[right - 1]) right--;
                    while (right > left && nums[left] == nums[left + 1]) left++;

                    // 找到答案时,双指针同时收缩
                    right--;
                    left++;
                }
            }
        }
        return result;
    }
};
18. 四数之和

给你一个由 n 个整数组成的数组 nums ,和一个目标值 target 。请你找出并返回满足下述全部条件且不重复的四元组 [nums[a], nums[b], nums[c], nums[d]] (若两个四元组元素一一对应,则认为两个四元组重复):

0 <= a, b, c, d < n

a、b、c 和 d 互不相同

nums[a] + nums[b] + nums[c] + nums[d] == target

你可以按 任意顺序 返回答案 。

解法:双指针解法,与三数之和的思路相同,都是左右指针同时向中间收缩,不同的是,在当前元素的for循环之外再加上一层for循环,即a=当前元素,b=a+1,left=b+1,right=nums.size()-1

class Solution {
public:
    vector<vector<int>> fourSum(vector<int>& nums, int target) {
        //创建一个二维数组
        vector<vector<int>> result;
        //快速排序,从小到大
        sort(nums.begin(),nums.end());
        //第一层遍历
        for(int i=0;i<nums.size();i++)
        {
            //如果排序后的数组第一个元素大于target,则不存在a+b+c+d等于target的情况了,就直接返回结果
            if(nums[i]>target && nums[i]>=0)
            {
                break;
            }
            //去重
            if(i>0 && nums[i]==nums[i-1])
            {
                continue;
            }
            //第二层遍历
            for(int j=i+1;j<nums.size();j++)
            {
                //如果前两个元素之和大于target,则不存在a+b+c+d等于target的情况了,就直接返回结果
                if (nums[j] + nums[i] > target && nums[j] + nums[i] >= 0) {
                    break;
                }
                // 对nums[j]去重
                if (j > i + 1 && nums[j] == nums[j - 1]) {
                    continue;
                }
                //定义左右指针
                int left=j+1;
                int right=nums.size()-1;
                while(right>left)
                {
                    //和大于target,右指针收缩
                    if((long) nums[i]+nums[j]+nums[left]+nums[right]>target) right--;
                    //和小于target,左指针收缩
                    else if((long) nums[i]+nums[j]+nums[left]+nums[right]<target) left++;
                    else
                    {
                        //和等于target,写入二维数组
                        result.push_back(vector<int>{nums[i],nums[j],nums[left],nums[right]});
                        //去重
                        while (right > left && nums[right] == nums[right - 1]) right--;
                        while (right > left && nums[left] == nums[left + 1]) left++;
                        //左右指针同时收缩
                        left++;
                        right--;
                    }
                }
            }
        }
        return result;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我来回答你的问题。首先,广度优先搜索(BFS)是一种图搜索算法,可以用来解决一些问题,比如迷宫问题。在迷宫问题中,我们需要找到一条从起点到终点的最短路径。下面是用 Python 实现 BFS 解决迷宫问题的示例代码: ```python from collections import deque # 定义一个二维数组表示迷宫,0 表示可以走,1 表示障碍物 maze = [ [0, 1, 0, 0, 0], [0, 1, 0, 1, 0], [0, 0, 0, 0, 0], [0, 1, 1, 1, 0], [0, 0, 0, 1, 0], ] # 定义起点和终点 start = (0, 0) end = (4, 4) # 定义四个方向,上下左右 directions = [(-1, 0), (1, 0), (0, -1), (0, 1)] def bfs(maze, start, end): # 定义队列,初始时将起点加入队列 queue = deque([start]) # 定义 visited 集合,用于记录已经访问过的位置 visited = set([start]) while queue: # 取出队列中的第一个节点 node = queue.popleft() # 如果当前节点是终点,返回到达终点的最短距离 if node == end: return distance[node[0]][node[1]] # 对于当前节点,遍历它的四个方向 for direction in directions: # 计算出下一个节点的坐标 next_node = (node[0] + direction[0], node[1] + direction[1]) # 如果下一个节点不越界且没有访问过,并且可以走(maze[next_node[0]][next_node[1]] == 0),将它加入队列和 visited 集合 if 0 <= next_node[0] < len(maze) and 0 <= next_node[1] < len(maze[0]) and next_node not in visited and maze[next_node[0]][next_node[1]] == 0: queue.append(next_node) visited.add(next_node) # 如果没有找到到达终点的路径,返回 -1 return -1 # 计算每个位置到起点的最短距离 distance = [[float('inf') for _ in range(len(maze[0]))] for _ in range(len(maze))] distance[start[0]][start[1]] = 0 bfs(maze, start, end) ``` 在上面的代码中,我们首先定义了一个迷宫,然后定义了起点和终点。接着,我们定义了四个方向,上下左右。接下来,我们定义了 bfs 函数,用于实现广度优先搜索。在 bfs 函数中,我们首先定义了一个队列和 visited 集合,用于记录已经访问过的位置。然后,我们将起点加入队列和 visited 集合。接着,我们进行循环,取出队列中的第一个节点,遍历它的四个方向。如果下一个节点不越界且没有访问过,并且可以走,我们将它加入队列和 visited 集合。最后,如果没有找到到达终点的路径,返回 -1。 最后,我们计算每个位置到起点的最短距离,并调用 bfs 函数求解最短路径。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值