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

news2025/1/12 20:59:00

前言

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

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;
    }
};

结语

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

加油吧

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

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

相关文章

RAG相关内容介绍

本文记录在查找RAG相关内容时所整合的一些资料与内容&#xff0c;还有一个组会报告的PPT 文章目录 定义LLM的知识更新难题 RAG是什么&#xff1f;-“开卷考试”RAG原理与技术RAG技术细节一、数据索引• 数据提取• 分块&#xff08;Chunking&#xff09;分块方式确定应用程序的…

本地编译安装 Minkowski Engine 报错 Cuda 版本 与 Pytorch 版本不匹配

编译 Cuda 版本 C 插件 Cuda 版本 与 Pytorch 版本不匹配解决方案 报错详情环境报错分析 报错详情 RuntimeError: The detected CUDA version (12.2) mismatches the version that was used to compile PyTorch (11.8). Please make sure to use the same CUDA versions.环境 …

WebSocket是什么以及其与HTTP的区别

新钛云服已累计为您分享774篇技术干货 HTTP协议 HTTP是单向的&#xff0c;客户端发送请求&#xff0c;服务器发送响应。举个例子&#xff0c;当用户向服务器发送请求时&#xff0c;该请求采用HTTP或HTTPS的形式&#xff0c;在接收到请求后&#xff0c;服务器将响应发送给客户端…

IOC - Google Guice

Google Guice是一个轻量级的依赖注入框架&#xff0c;专注于依赖注入和IoC&#xff0c;适用于中小型应用。 Spring Framework是一个全面的企业级框架&#xff0c;提供了广泛的功能&#xff0c;适用于大型企业应用。 是吧&#xff01;IOC 容器不止Spring,还有Google Guice,来体…

钉钉统计部门个人请假次数go

前言 最近小组需要统计部门各种请假次数&#xff0c;写了一个方法&#xff0c;第一次实战中用到递归函数&#xff0c;简单记录一下。 效果展示 这些数据不需要返回json&#xff0c;这里这样是为了方便测试。可以通过这些数据完成其它的操作。 功能实现 钉钉服务端调试工具A…

linux入门---线程池的模拟实现

目录标题 什么是线程池线程的封装准备工作构造函数和析构函数start函数join函数threadname函数完整代码 线程池的实现准备工作构造函数和析构函数push函数pop函数run函数完整的代码 测试代码 什么是线程池 在实现线程池之前我们先了解一下什么是线程池&#xff0c;所谓的池大家…

C语言——求 n 以内(不包括 n)同时能被 3 和 7 整除的所有自然数之和的平方根 s,n 从键盘输入。

#define _CRT_SECURE_NO_WARNINGS 1#include<stdio.h> #include<math.h> int main() {int i,n;double s0.0;printf("输入任意一个自然数&#xff1a; ");scanf("%d",&n);for(i1;i<n;i) {if(i%30&&i%70){si;}}ssqrt(s);printf(…

低价寄快递寄件微信小程序 实际商用版,对接了低价快递渠道,运营平台赚取差价,支持市面上全部主流快递

盈利模式 快递代下CPS就是用户通过线上的渠道&#xff08;快递小程序&#xff09;&#xff0c;线上下单寄快递来赚取差价&#xff0c;例如你的成本价是5元&#xff0c;你在后台比例设置里面设置 首重利润是1元&#xff0c;续重0.5元&#xff0c;用户下1kg的单页面显示的就是6元…

JAVA集合学习

一、结构 List和Set继承了Collection接口&#xff0c;Collection继承了Iterable Object类是所有类的根类&#xff0c;包括集合类&#xff0c;集合类中的元素通常是对象&#xff0c;继承了Object类中的一些基本方法&#xff0c;例如toString()、equals()、hashCode()。 Collect…

Linux —— 网络编程套接字

目录 一&#xff0c;网络字节序 二&#xff0c;socket编程接口 sockaddr结构 源IP地址、目的IP地址&#xff0c;在IP数据包头部&#xff0c;有此两个IP地址&#xff1b; 端口号&#xff0c;是传输层协议的内容&#xff1b; 端口号是一个2字节16位的整数&#xff1b;端口号用…

第 117 场 LeetCode 双周赛题解

A 给小朋友们分糖果 I 动态规划&#xff1a;设 p [ k ] [ i ] p[k][i] p[k][i] 为将 i i i 个糖果分给 k k k 个小朋友的方案数&#xff0c;先求 p [ 2 ] [ i ] p[2][i] p[2][i] &#xff0c;再求 p [ 3 ] [ n ] p[3][n] p[3][n] class Solution { public:using ll long …

API SIX系列-服务搭建(一)

APIsix简介 APISIX是一个微服务API网关&#xff0c;具有高性能、可扩展性等优点。它基于nginx&#xff08;openresty&#xff09;、Lua、etcd实现功能&#xff0c;借鉴了Kong的思路。和传统的API网关相比&#xff0c;APISIX具有较高的性能和较低的资源消耗&#xff0c;并且具有…

SpringBoot--中间件技术-2:整合redis,redis实战小案例,springboot cache,cache简化redis的实现,含代码

SpringBoot整合Redis 实现步骤 导pom文件坐标 <!--redis依赖--> <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId> </dependency>yaml主配置文件&#xff0c;配置…

代码随想录 Day43 动态规划11 LeetCode T309 买卖股票的最佳时期含冷冻期 T714买卖股票的最佳时机含手续费

LeetCode T309 买卖股票的最佳时机含冷冻期 题目链接:309. 买卖股票的最佳时机含冷冻期 - 力扣&#xff08;LeetCode&#xff09; 题目思路: 这题其实就是将卖出的状态拆分成三个状态 1.前两天就卖出并一直保持卖出的状态 2.今天卖出的状态 3.今天是冷冻期的状态 当然还有一个…

ElasticSearch中常见的分词器介绍

文章目录 ElasticSearch中常见的分词器介绍前言分词器的作用如何指定分词器分词器的组成分词器的类型标准分词器空格分词器简单分词器关键词分词器停用词分词器IK分词器NGram分词器正则匹配分词器语言分词器自定义分词器 ElasticSearch中常见的分词器介绍 前言 ElasticSearch是…

泛微E-Office信息泄露漏洞复现

简介 Weaver E-Office是中国泛微科技&#xff08;Weaver&#xff09;公司的一个协同办公系统。 Weaver E-Office 9.5版本存在安全漏洞。攻击者利用该漏洞可以访问文件或目录。 漏洞编号&#xff1a;CVE-2023-2766 漏洞复现 FOFA语法&#xff1a; app"泛微-EOffice&qu…

Linux系统编程,Linux中的文件读写文件描述符

文章目录 Linux系统编程&#xff0c;Linux中的文件读写操作1.open函数&#xff0c;打开文件 Linux系统编程&#xff0c;Linux中的文件读写操作 1.open函数&#xff0c;打开文件 我们来看下常用的open函数 这个函数最终返回一个文件描述符struct file 我们查看一下它的Ubuntu…

[工业自动化-14]:西门子S7-15xxx编程 - 软件编程 - STEP7 TIA博途是全集成自动化软件TIA portal快速入门

目录 一、TIA博途是全集成自动化软件TIA portal快速入门 1.1 简介 1.2 软件常用界面 1.3 软件安装的电脑硬件要求 1.4 入口 1.5 主界面 二、PLC软件编程包含哪些内容 2.1 概述 2.2 电机运动控制 一、TIA博途是全集成自动化软件TIA portal快速入门 1.1 简介 Siemens …

java 继承和多态 (图文搭配,万字详解!!)

目录 1.继承 1.1 为什么需要继承 1.2 继承概念 1.3 继承的语法 1.4 父类成员访问 1.4.1 子类中访问父类的成员变量 1.4.2 子类中访问父类的成员方法 1.5 super关键字 1.6 子类构造方法 1.7 super和this 1.8 再谈初始化 1.9 protected 关键字 1.10 继承方式 1.11 f…

2560 动物保护宣传网站设计JSP【程序源码+文档+调试运行】

摘要 本文介绍了一个动物保护宣传网站的系统的设计与实现。该系统包括前台用户模块和后台管理员模块&#xff0c;具有用户注册/登录、新闻、资源库、法律法规、图片赏析、留言板、关于我们、用户后台等功能。通过数据库设计和界面设计&#xff0c;实现了系统的基本功能&#x…