【刷题】力扣每日一题 : 381、2300、765

前言

本篇文章用于记录在做力扣每日一题的时候遇到的一些知识点以及自己的思路

381

题干

题目链接

我的思路及做题过程

思路1

我的想法是 记录每个字符串的字母出现个数 然后比较两个字符串是否有字母同时出现

class Solution {
public:
    int judge(string s1, string s2, int l1, int l2) {
        int n1[30] = { 0 }, n2[30] = { 0 };

        for (int i = 0; i < l1; i++) {
            n1[s1[i] - 97]++;
        }
        for (int i = 0; i < l2; i++) {
            n2[s2[i] - 97]++;
        }
        for (int i = 0; i < 26; i++) {
            if (n1[i] * n2[i] > 0) {
                return 0;
            }
        }
        return l1 * l2;
    }

    int maxProduct(vector<string>& words) {
        for (int i = 0; i < words.size(); i++) {
            for (int j = 0; j < words.size(); j++) {
                le = judge(words[i], words[j], words[i].size(), words[j].size());

                if (le > max) {
                    max = le;
                }
            }
        }
        return max;
    }
private:
    int num[1010], le, max = 0;
};

re了 我写的时候就感觉它会re

优化1

judge函数没必要去记录字母出现个数 直接两两比较 如果相等直接返回0即可

    int judge(string s1, string s2, int l1, int l2) {
        for (int i = 0; i < l1; i++){
            for (int j = 0; j < l2; j++) {
                if (s1[i] == s2[j]){
                    return 0;
                }
            }
        }
        return l1 * l2;
    }

优化2

maxProduct函数中for循环的范围可以修改一下(比较简单的优化方式)
j的范围变为

            for (int j = i + 1; j < words.size(); j++) {

优化3

数据比较大的时候 每次调用judge函数都需要比较长的运行时间
我们可以进一步缩小使用judge函数的范围

当l1*l2>max的时候 再去进行一一比较

最终代码

class Solution {
public:
    int judge(string s1, string s2, int l1, int l2, int max) {
        if(l1 * l2 > max){
            for (int i = 0; i < l1; i++) {
                for (int j = 0; j < l2; j++) {
                    if (s1[i] == s2[j]) {
                        return 0;
                    }
                }
            }
            return l1 * l2;
        }
        return 0;
    }

    int maxProduct(vector<string>& words) {

        for (int i = 0; i < words.size(); i++) {
            for (int j = i + 1; j < words.size(); j++) {
                le = judge(words[i], words[j], words[i].size(), words[j].size(), max);
                if(le){
                    max = le;
                }
            }
        }
        return max;
    }
private:
    int num[1010], le, max = 0;
};

题解中的其他做法

位运算

跟我的思路一有一些相同之处 : 统计每个字母出现次数
不同的是 它使用了位运算
移位操作符、按位或 和 &

先计算出每个单词中有什么字母出现(数组的映射 不再解释了) 左移一位
之后与原数值进行按位或

                masks[i] |= 1 << (word[j] - 'a');

最后 将两个数组中的值进行按位与 为0 就与max进行比较
(位运算太妙了

还有用哈希表进行优化的 (我是蒟蒻 我不会 呜呜呜呜呜呜呜呜呜

2300

题干

题目链接

我的思路及做题过程

思路1

第一遍写的时候
我直接两个for循环遍历了一下

re了 很正常 毕竟是中等题

思路2

二分法双指针
先用sort排序 之后再利用双指针 逐渐缩小范围 减少程序运行时间

二分法部分的代码

int le = 0, ri = po.size() - 1, mid;
while (le <= ri)
{
	mid = (le + ri) / 2;
	
	a = sp[i], b = po[mid];
	
	if (a * b < su)
	{
	    le = mid + 1;
	}
	else
	{
	    ri = mid - 1;
	}
}

最终代码

class Solution {
public:
    vector<int> successfulPairs(vector<int>& sp, vector<int>& po, long long su) {
        sort(po.begin(), po.end());

        for (int i = 0; i < sp.size(); i++)
        {
            int le = 0, ri = po.size() - 1, mid;
            while (le <= ri)
            {
                //mid = le + (ri - le) >> 1;
                mid = (le + ri) / 2;

                a = sp[i], b = po[mid];

                if (a * b < su)
                {
                    le = mid + 1;
                }
                else
                {
                    ri = mid - 1;
                }
            }
            pairs.push_back(po.size() - le);
        }
        return pairs;
    }

private:
    vector<int>pairs;
    long long a, b, c;
};

注意点

在学习二分算法的时候 我们肯定都接触过位运算 并且知道位运算比乘除法要快
那在这道题中 我们可不可以用位运算呢 大家可以试一下
下面提供一下我调试时的代码

class Solution {
public:
    vector<int> successfulPairs(vector<int>& sp, vector<int>& po, long long su) {
        sort(po.begin(), po.end());

        for (int i = 0; i < sp.size(); i++)
        {
            int le = 0, ri = po.size() - 1, mid;
            while (le <= ri)
            {
                mid = le + (ri - le) >> 1;
                a = sp[i], b = po[mid];

                if (a * b < su)
                {
                    le = mid + 1;
                }
                else
                {
                    ri = mid - 1;
                }
            }
            pairs.push_back(po.size() - 1);
        }
        return pairs;
    }

private:
    vector<int>pairs;
    int flag = 1;
    long long x = 0;
    long long a, b, c;
};


int main() {
    Solution s1;
    vector<int>po, sp;
    po.push_back(1);
    po.push_back(2);
    po.push_back(3);
    po.push_back(4);
    po.push_back(5);
    sp.push_back(5);
    sp.push_back(1);
    sp.push_back(3);
    s1.successfulPairs(sp, po, 7);

    return 0;
}

答案是不可以 会陷入死循环

分析

我们先循环两次 变成下面这种情况
在这里插入图片描述

接下来关键的要来了
我们来到第三次循环 遇到了这条语句

mid = left + (right - left) >>1;

那么(right - left)此时是 1-1 为0
0>>1仍未0
接下来进入if的第一种情况

left = mid + 1;

left = 1

第四次循环中与第三次循环情况相同
所以 陷入了死循环

mid = (le + ri) / 2;

不会死循环 因为1+1/2 == 1

题解中的其他做法

我看到官解中虽然思路和我写的差不多 但是他用到了新的知识
upper_bound函数它返回一个迭代器,指向在排序序列中第一个大于或等于给定值的元素。如果不存在大于或等于给定值的元素,则返回序列的尾迭代器

lower_bound和upper_bound的区别是后者返回的是大于给定值的元素的迭代器
前者返回的是大于等于给定值元素的迭代器

lower_bound( begin,end,num):从数组的begin位置到end-1位置二分查找第一个大于或等于num的数字,找到返回该数字的地址,不存在则返回end。通过返回的地址减去起始地址begin,得到找到数字在数组中的下标。

upper_bound( begin,end,num):从数组的begin位置到end-1位置二分查找第一个大于num的数字,找到返回该数字的地址,不存在则返回end。通过返回的地址减去起始地址begin,得到找到数字在数组中的下标。

765

温馨提示

下面是我写着玩的 能过纯粹是数据量小
所以下面的题解也不具有参考性

题干

题目链接

我的思路及做题过程

第一遍代码

class Solution {
public:
    int minSwapsCouples(vector<int>& row) {
        for (int i = 1; i < row.size(); i++) {
            if (!(abs(row[i - 1] - row[i]) == 1)) {
                for (int j = i; j < row.size(); j++) {
                    if ((abs(row[j] - row[i]) == 1)) {
                        swap(row[j], row[i]);
                        num++;
                        break;
                    }
                }
            }
        }
        return num;
    }
private:
    int num = 0;
};

惨不忍睹

问题

我找出来了两个问题

1. for循环
我因为担心越界 所以把范围写成1~n-1

但实际上 可以一对一对的去判断(并且题目已经说明row的长度是偶数) 即i += 2

2. if语句
if语句的判断条件有问题
不能用取绝对值的方法 因为2 和 3不是一对 但绝对值是1 这不符合题意
可以通过判断奇偶性 来进行加一或者减一

修改之后的代码

class Solution {
public:
    int minSwapsCouples(vector<int>& row) {
        for (int i = 0; i < row.size(); i += 2) {
            if (((row[i] % 2 == 0) ? row[i] + 1 : row[i] - 1) != row[i + 1]) {
                for (int j = i + 2; j < row.size(); j++) {
                    if (((row[i] % 2 == 0) ? row[i] + 1 : row[i] - 1) == row[j]) {
                        swap(row[j], row[i + 1]);
                        num++;
                    }
                }
            }
        }
        return num;
    }
private:
    int num = 0;
};

题解中的其他做法

官解中的并查集和bfs我都不会 所以没仔细看
我在其他的题解中看到了一种做法 利用异或

以下代码转自
这个博主的解法

简单来说就是 2和3这一对情侣 通过与1异或可以得到另一半(又是美妙 的位运算)

class Solution {
public:
    //参考大佬的异或,2与1异或得到3,3与1异或得到2;也就是说每一对只要异或就能得到彼此的“另一半”,只要找到并交换就行
    int minSwapsCouples(vector<int>& row) {
        int n = row.size();
        int cnt = 0;
    
        for(int i = 0; i < n - 1; i++){
            int x = row[i];   //某个人
            int y = x ^ 1;  //他的另一半

            if(row[i + 1] != y){  //情侣不挨着,就往后搜
                for(int k = i + 2; k < n; k++){
                    if(row[k] == y){
                        //找到了另一半,交换
                        int temp = row[i + 1];
                        row[i + 1] = row[k];
                        row[k] = temp;
                        cnt++;
                        break;   //找到就退回上一层循环,判断下一对是不是情侣坐一起
                    }
                }
            }
        }
        return cnt;
    }
};

结语

我打算新开一个刷题的专栏 用于总结复盘

加油吧

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

asp.net core自定义异常过滤器并记录到Log4Net日志

1.创建异常过滤器特性 using Log4Net.Controllers; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Filters;namespace Log4NetTest {public class CustomerExceptionFilterAttribute : Attribute, IExceptionFilter{private readonly ILogger<CustomerE…

CSS布局001:画各种三角形

CSS实战中&#xff0c;有很多时候采用css来绘制三角形&#xff0c;而不是采用图片的方式&#xff0c;这样有利于快速成型&#xff0c;不用多调用服务器数据。 CSS代码 上三角 #triangle-up {width: 0;height: 0;border-left: 50px solid transparent;border-right: 50px solid…

idea配置tomcat参数,防止nvarchar保存韩文、俄文、日文等乱码

描述下我的场景&#xff1a; 数据库服务器在远程机器上&#xff0c;数据库使用的Oracle&#xff0c;字符集是ZHS16GBK&#xff0c;但保存韩文、俄文、日文等字段A的数据类型是nvarchar(120)&#xff0c;而nvarchar使用的是Unicode 编码&#xff0c;有点乱。。 遇到的问题&…

ArcGIS:如何迭代Shp文件所有要素并分别导出为Shp文件?

01 前言 尝试用IDL实现&#xff0c;奈何又涉及新的类IDLffShape&#xff0c;觉得实在没有必要学习的必要&#xff0c;毕竟不是搞开发&#xff0c;只是做做数据处理&#xff0c;没必要拿IDL不擅长的且底层的东西自己造轮子。 这里想到使用Python去解决&#xff0c;gdal太久没用…

微信的聊天记录导出到网页中的最快方法,语音能听,图片视频能看

12-7 如果你有把微信的聊天记录导出到表格或者网页上的需求&#xff0c;适合看看本文章&#xff0c;本文的方法可以让你把微信的聊天记录导出备份&#xff0c;可以在完全脱离微信的情况下随时调取查看聊天数据。 本文介绍的软件可以导出两种格式的聊天记录备份文件&#xff0…

【C语言】冒泡排序(图解)

&#x1f308;write in front :&#x1f50d;个人主页 &#xff1a; 啊森要自信的主页 &#x1f308;作者寄语 &#x1f308;&#xff1a; 小菜鸟的力量不在于它的体型&#xff0c;而在于它内心的勇气和无限的潜能&#xff0c;只要你有决心&#xff0c;就没有什么事情是不可能的…

wsl [Ubuntu20.04.6] 安装 Hadoop

文章目录 1.安装WSL2.安装Java安装Hadoop3.3配置文件1.修改hadoop-env.sh2.修改core-site.xml3.修改hdfs-site.xml ssh启动 1.安装WSL 重启电脑 管理员打开powershell PS C:\windows\system32> wsl --list --online PS C:\windows\system32> wsl --install -d Ubuntu-2…

OpenCV图像坐标系

绘制代码: X轴 # 选取两个点 point1 = (20, 0) point2 = (200, 0)# 在图像上绘制连接线 cv2.line(img, point1, point2, (

NSSCTF-Crypto入门题 练习记录贴 ‘‘一‘‘

文章目录 前言001[鹤城杯 2021]easy_crypto002[强网拟态 2021]拟态签到题003[SWPUCTF 2021 新生赛]crypto8004[SWPUCTF 2021 新生赛]crypto7005[SWPUCTF 2021 新生赛]crypto6006[SWPUCTF 2021 新生赛]ez_caesar007[SWPUCTF 2021 新生赛]crypto10008[鹤城杯 2021]A_CRYPTO009[SW…

Spring -Spring之循环依赖源码解析

什么是循环依赖&#xff1f; 很简单&#xff0c;就是A对象依赖了B对象&#xff0c;B对象依赖了A对象。 比如&#xff1a; // A依赖了B class A{public B b; }// B依赖了A class B{public A a; }那么循环依赖是个问题吗&#xff1f; 如果不考虑Spring&#xff0c;循环依赖并…

SparkSQL语法优化

SparkSQL在整个执行计划处理的过程中&#xff0c;使用了Catalyst 优化器。 1 基于RBO的优化 在Spark 3.0 版本中&#xff0c;Catalyst 总共有 81 条优化规则&#xff08;Rules&#xff09;&#xff0c;分成 27 组&#xff08;Batches&#xff09;&#xff0c;其中有些规则会被归…

junit写搜索树测试

用法 assertTrue(range.contains("Two")); 2个参数,右边错就打印左边. AbstractSelfBalancingBinarySearchTree abt; AbstractBinarySearchTree.Node node; Before public void setUp() { abt new AbstractSelfBalancingBinarySearchTree() { Override protecte…

【深度挖掘Java性能调优】「底层技术原理体系」深入挖掘和分析如何提升服务的性能以及执行效率(引导篇)

深入挖掘和分析如何提升服务的性能以及执行效率 前提介绍知识要点 性能概述教你看懂程序的性能案例介绍性能指标性能的参考指标性能瓶颈&#xff08;木桶原理&#xff09; 性能分析三大定律Amdahl定律计算公式参数解释案例分析定律总结 Gustafson定律与Amdahl定律相对立Gustafs…

Panda3d 场景管理

Panda3d 场景管理 文章目录 Panda3d 场景管理有关分层场景图的重要信息NodePathNodePath 以及 Node 的函数调用模型文件文件格式加载模型文件将模型放置在场景图中模型缓存压缩模型异步加载模型通过回调函数进行 常见的状态变化修改节点的位置和姿态改变父级节点改变颜色隐藏和…

【多线程 - 01、概述】

进程 几乎所有的操作系统都支持进程概念&#xff0c;进程是处于运行过程中的程序&#xff0c;进程是操作系统中进行资源分配的基本单位。 三个基本特征 独立性&#xff1a;指进程实体是一个能独立运行、独立获得资源和独立接受调度的基本单位。而对于未建立任何进程的程序&…

深度学习模型基于Python+TensorFlow+Django的垃圾识别系统

欢迎大家点赞、收藏、关注、评论啦 &#xff0c;由于篇幅有限&#xff0c;只展示了部分核心代码。 文章目录 一项目简介 二、功能三、系统四. 总结 一项目简介 要使用Python、TensorFlow和Django构建一个垃圾识别系统&#xff0c;您可以按照以下步骤进行操作&#xff1a; 安装…

android studio 修改图标

Android Studio 修改图标 简介 Android Studio 是一款由谷歌推出的用于开发 Android 应用程序的集成开发环境&#xff08;IDE&#xff09;。在开发过程中&#xff0c;我们可以根据自己的需求修改 Android Studio 的图标&#xff0c;以个性化我们的开发环境。 本文将介绍如何在…

魔搭社区LLM模型部署实践, 以ChatGLM3为例(一)

魔搭社区LLM模型部署实践&#xff0c; 以ChatGLM3为 例 本文以ChatGLM3-6B为例&#xff0c; 主要介绍在魔搭社区如何部署LLM&#xff0c; 主要包括如下内容&#xff1a; ● SwingDeploy - 云端部署&#xff0c; 实现零代码一键部署 ● 多端部署 - MAC个人笔记本&#xff0c;…

[PHP]Kodexplorer可道云 v4.47

KodExplorer可道云&#xff0c;原名芒果云&#xff0c;是基于Web技术的私有云和在线文件管理系统&#xff0c;由上海岱牧网络有限公司开发&#xff0c;发布于2012年6月。致力于为用户提供安全可控、可靠易用、高扩展性的私有云解决方案。 用户只需通过简单环境搭建&#xff0c;…

【m98】webrtc vs2017构建带符号的debug库

调试有符号 调试 无符号 试试exe不输出到独立的文件? -】 直接输出到sln下面