leetcode 力扣刷題 數組交集(數組、set、map都可實現哈希表)

數組交集

  • 349. 兩個數組的交集
    • 排序+雙指針
    • 數組實現哈希表
    • unordered_set
    • unordered_map
  • 350. 兩個數組的交集Ⅱ
    • 排序 + 雙指針
    • 數組實現哈希表
    • unordered_map

349. 兩個數組的交集

題目鏈接:349. 兩個數組的交集
題目內容如下,理解題意:①交集中每個元素是唯一的,只能出現一次,所以本題要找的是同時出現在數組nums1和nums2中的元素,但是并不關心他們出現的次數;②輸出結果的順序不用考慮,也就是只要找到了同時出現在nums1和nums2中的元素就行,可以給數組排序(打亂了原本的順序)再去查找、可以用map、set(其中key是無序的)……
在這里插入圖片描述
這個題目暴力求解是可以的,暴力求解兩層循環,將nums1和nums2的元素逐個對比,時間復雜度是O(m*n),因為nums1和nums2的長度都<=1000,所以最終也是能夠運行的。
考慮更優的解法,直接一遍遍歷nums1和nums2就好了。以下詳述各解法:

排序+雙指針

解法Ⅰ,對nums1和nums2排序后,從頭開始遍歷兩個數組(下標用index1和index2),并將nums1[index1] = nums2[index2]的元素加入結果數組中。
存在的問題是:因為nums1和nums2中存在重復元素,如果找到了nums1[index1] = nums2[index2],且在nums1中,nums1[index1] 有重復,即nums1[index1+1] = nums1[index1] ,且在nums2中,nums2[index2]有重復,即nums2[index2+1] = nums2[index2]。那么直接對index++和index2++,會向結果數組中添加重復的元素。
解決:找到nums1[index1] = nums2[index2]后,index1++直到找到與之不同的下一個元素(就是跳過中間的相同的元素);index2++同樣。
在這里插入圖片描述

代碼實現(C++):

class Solution {
public:vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {vector<int> ans;sort(nums1.begin(),nums1.end());//先給nums1和nums2都排序sort(nums2.begin(),nums2.end());//排序后雙指針(index1和index2遍歷nums1和nums2for(int index1 = 0, index2 = 0; index1 < nums1.size() && index2 < nums2.size();){if(nums1[index1] == nums2[index2]){ans.emplace_back(nums1[index1]);    //如果找到在兩個數組中出現的元素,加入到結果數組中//之后直接跳過和當前元素相同的一截,避免有可能向ans中重復添加該元素的可能do{index1++;}while(index1 < nums1.size() && nums1[index1] == nums1[index1 - 1]);do{index2++;}while(index2 < nums2.size() && nums2[index2] == nums2[index2 - 1]);}//如果不相等,更小的那個數向后移,同樣是跳過和當前元素相同的一截,避免重復的比較else  if( nums1[index1] < nums2[index2]){do{index1++;}while(index1 < nums1.size() && nums1[index1] == nums1[index1 - 1]);                }else{do{index2++;}while(index2 < nums2.size() && nums2[index2] == nums2[index2 -1]);                }}return ans;}
};

數組實現哈希表

哈希表的好處體現在,它能夠快速查找一個元素是否存在,時間復雜度是O(1)。我們要找nums1和nums2中同時存在的元素,換句話——查找nums1中某個元素是否出現在了nums2中。那么就可以用哈希表。因為題目中,nums1和num2的長度以及其中的int元素的大小都給了限制(<=1000),那么可以用數組來實現哈希表。
直接定義長度為1001的int數組count_1和count_2,統計nums1中元素的次數和nums2中元素出現的次數,最后對比count_1和count_2的每位元素,如果同時不為0的話,將對應元素加入到ans中。
代碼如下(C++):

class Solution {
public:vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {int count_1[1001] = {0}, count_2[1001] = {0};vector<int> ans;//分別統計nums1和nums2中元素出現情況for ( auto& num : nums1){count_1[num]=1;}for ( auto& num : nums2){            count_2[num]++;}for ( int i = 0; i <= 1000; i++){//在兩個數組中出現次數均>=1時,加入ans中if( count_1[i] && count_2[i])ans.emplace_back(i);}return ans;}
};

優化:上面需要用到兩個數組count_1和count_2來分別統計nums1、nums2中元素出現的情況,之后還要遍歷這倆數組。是否有可能只使用一個count數組,用兩次?——遍歷nums1的時候,出現的元素不統計次數,而是count[nums[i]]=1,標記該元素出現過;遍歷nums2的時候,如果count[nums2[j]] !=0就表示在兩個數組中同時存在;防止重復添加,再將count[nums2[j]]=0;
代碼實現(C++):

class Solution {
public:vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {int count[1001] = {0};vector<int> ans;//統計nums1中元素的出現情況for ( auto& num : nums1){count[num]=1;}//遍歷nums2for ( auto& num : nums2){if(count[num]){ //同時判斷nums2中的元素在nums1中是否出現count[num]=0;ans.emplace_back(num);}}      return ans;}
};

unordered_set

題意是要找交集,那么直接把數組變成集合,然后求兩個集合交集就好。實現上,將vector變成unordered_set,然后對比兩個unordered_set的key,找到重疊部分。
代碼實現(C++):

class Solution {
public:vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {//把vector轉化成unordered_setunordered_set<int> num_set1(nums1.begin(),nums1.end());unordered_set<int> num_set2(nums2.begin(),nums2.end());vector<int> ans;//遍歷兩個set,找交集;遍歷size小的if( num_set1.size() < num_set2.size()){for( auto& key : num_set1)if(num_set2.count(key))ans.emplace_back(key);}else{for( auto& key :num_set2)if(num_set1.count(key))ans.emplace_back(key);}return ans;}
};

unordered_map

最后也能用map來實現,遍歷nums1和nums2的同時,統計其中元素出現的次數,用unordered_map來存,key是數組中出現的元素,value是元素出現的次數; 之后找到兩個map中重合的key。
代碼(C++):

class Solution {
public:vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {unordered_map<int,int> count_1, count_2; vector<int> ans;//用map統計數組中出現的元素及其次數for ( auto& num : nums1){count_1[num]++;}for ( auto& num : nums2){count_2[num]++;}if(count_1.size() < count_2.size()){for ( auto key_value : count_1)if(count_2.count(key_value.first))ans.emplace_back(key_value.first);}else{for ( auto key_value : count_2)if(count_1.count(key_value.first))ans.emplace_back(key_value.first);}return ans;}
};

350. 兩個數組的交集Ⅱ

題目鏈接:350. 兩個數組的交集Ⅱ
題目內容:在這里插入圖片描述
這道題和上一題唯一不同的點在于:在nums1和nums2中同時出現的元素,如果出現次數不止一次,都需要加入到結果中。即不僅要統計同時出現在nums1和nums2中的元素,還要統計他們各自出現的次數(C1和C2),并在結果數組ans中重復min (C1, C2) 次。以下代碼均在上一題基礎上做一點改動即可。

排序 + 雙指針

排序后數組元素逐個對比就好:雙指針index1和index2,每次對比nums1[index1]和nums2[index2]的關系后,直接index1++,index2++:


class Solution {
public:vector<int> intersect(vector<int>& nums1, vector<int>& nums2) {vector<int> ans;sort(nums1.begin(),nums1.end());sort(nums2.begin(),nums2.end());for(int index1 = 0, index2 = 0; index1 < nums1.size() && index2 < nums2.size();){if(nums1[index1] == nums2[index2]){ans.emplace_back(nums1[index1]);//下標直接向后移動,這樣同時重復出現在兩個數組中的元素能夠重復添加index1++;index2++;               }else  if( nums1[index1] < nums2[index2]){index1++;              }else{index2++;               }}return ans;}
};

數組實現哈希表

先用數組count統計nums1中出現的元素,及其次數;再遍歷nums2,同時出現在nums1中的元素,count[nums2[i]]- -,向結果數組ans中添加一次該元素。

class Solution {
public:vector<int> intersect(vector<int>& nums1, vector<int>& nums2) {int count[1001] = {0};vector<int> ans;//統計出現的元素,以及次數for ( auto& num : nums1){count[num]++;}for ( auto& num : nums2){if(count[num]){//對于同時出現的元素,對其次數--,保證后續再出現該元素時,還能重復添加count[num]--;ans.emplace_back(num);}          }      return ans;}
};

unordered_map

只是將上面的數組換成了unordered_map。用數組實現哈希表適用于nums1和nums2都不大的,并且其中元素也不大的情況,當數組很大并且數組元素為int,大小沒有限制的時候,用map更合適(或者set)
代碼如下:

class Solution {
public:vector<int> intersect(vector<int>& nums1, vector<int>& nums2) {unordered_map<int,int> count;vector<int> ans;for(auto& num : nums1){count[num]++;}for(auto& num : nums2){if(count.count(num)){ans.emplace_back(num);count[num]--;//如果已經重復添加了min(c1,c2)次了,即便后續再出現也不能再添加了if(count[num]==0)count.erase(num);}}return ans;}
};

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/40192.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/40192.shtml
英文地址,請注明出處:http://en.pswp.cn/news/40192.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

梯度爆炸和梯度消失的原因以及解決方法

文章目錄 1、原因&#xff1a;2、解決方法 1、原因&#xff1a; 梯度消失和梯度爆炸的根本原因是因為在反向傳播過程中&#xff0c;使用鏈式法則計算時&#xff0c;累積相乘效應導致梯度過大或者過小主要原因有&#xff1a; 1&#xff09;激活函數&#xff1a;例如sigmoid或者…

聊聊火車的發展

目錄 1.火車的概念 2.火車的發展歷史 3.火車對戰爭的影響 4.火車對人們出行造成的影響 1.火車的概念 火車是一種由機械動力驅動的陸上交通工具&#xff0c;通常用來運輸人員和貨物。它由一列或多列的連接在一起的車廂組成&#xff0c;有軌道作為其行駛的基礎&#xff0c;并通…

重建與突破,探討全鏈游戲的現在與未來

全鏈游戲&#xff08;On-Chain Game&#xff09;是指將游戲內資產通過虛擬貨幣或 NFT 形式記錄上鏈的游戲類型。除此以外&#xff0c;游戲的狀態存儲、計算與執行等皆被部署在鏈上&#xff0c;目的是為用戶打造沉浸式、全方位的游戲體驗&#xff0c;超越傳統游戲玩家被動控制的…

mysql面試

基礎篇 通用語法及分類 DDL: 數據定義語言&#xff0c;用來定義數據庫對象&#xff08;數據庫、表、字段&#xff09;DML: 數據操作語言&#xff0c;用來對數據庫表中的數據進行增刪改DQL: 數據查詢語言&#xff0c;用來查詢數據庫中表的記錄DCL: 數據控制語言&#xff0c;用…

php正則替換文章的圖片

要使用正則表達式替換文章中的圖片鏈接&#xff0c;可以按照以下步驟進行操作&#xff1a; 1. 獲取文章內容&#xff1a;首先&#xff0c;你需要獲取包含圖片鏈接的文章內容。你可以從文件中讀取文章&#xff0c;或者從數據庫中檢索文章內容。 2. 使用正則表達式匹配圖片鏈接…

JAVA編程學習筆記

常用代碼、特定函數、復雜概念、特定功能……在學習編程的過程中你會記錄下哪些內容&#xff1f;快來分享你的筆記&#xff0c;一起切磋進步吧&#xff01; 一、常用代碼 在java編程中常用需要儲備的就是工具類。包括封裝的時間工具類。http工具類&#xff0c;加解密工具類&am…

day17 | 110.平衡二叉樹、257. 二叉樹的所有路徑、404.左葉子之和

目錄&#xff1a; 解題及思路學習 110.平衡二叉樹 https://leetcode.cn/problems/balanced-binary-tree/ 給定一個二叉樹&#xff0c;判斷它是否是高度平衡的二叉樹。 本題中&#xff0c;一棵高度平衡二叉樹定義為&#xff1a; 一個二叉樹每個節點 的左右兩個子樹的高度差…

Linux學習之firewallD

systemctl status firewalld.service查看一下firewalld服務的狀態&#xff0c;發現狀態是inactive (dead)。 systemctl start firewalld.service啟動firewalld&#xff0c;systemctl status firewalld.service查看一下firewalld服務的狀態&#xff0c;發現狀態是active (runni…

okcc呼叫系統導入呼叫名單/客戶資料的數量上限,okcc通話聲音小有哪幾種處理辦法?

系統導入呼叫名單/客戶資料的數量上限 呼叫名單一次最多十萬 客戶資料一次最多五萬 通話聲音小有哪幾種處理辦法&#xff1f; 1、IP話機&#xff1a;通過話機上的音量調節按鈕來進行調節。 2、模擬話機&#xff1a;修改語音網關上的增益來實現。 “ 往IP增益”表示電話呼入…

stable diffusion 運行時報錯: returned non-zero exit status 1.

運行sh run.sh安裝stable diffusion時報錯&#xff1a;ImportError: cannot import name builder from google.protobuf.internal (stable-diffusion-webui/venv/lib/python3.8/site-packages/google/protobuf/internal/__init__.py) 原因&#xff1a;python版本過低&#xff0…

ubuntu16.04制作本地apt源離線安裝

一、首先在有外網的服務器安裝需要安裝的軟件&#xff0c;打包deb軟件。 cd /var/cache/apt zip -r archives.zip archives sz archives.zip 二、在無外網服務器上傳deb包&#xff0c;并配置apt源。 1、上傳deb包安裝lrzsz、unzip 用ftp軟件連接無外網服務器協議選擇sftp…

股票交易c接口包含哪些調用函數?

股票交易的C接口中可能包含多個調用函數&#xff0c;具體的調用函數取決于所使用的接口規范和交易所的要求。接下來看看下面是一些可能常見的股票交易C接口調用函數的示例&#xff1a; 1. 連接函數&#xff08;Connect&#xff09;&#xff1a;用于與交易所建立網絡連接。 2.…

CSS(JavaEE初階系列14)

目錄 前言&#xff1a; 1.CSS是什么 1.1CSS基本語法 2.引入樣式 2.1內部樣式表 2.2行內樣式表 2.3外部樣式 3.選擇器 3.1選擇器的種類 3.1.1基礎選擇器 3.1.2復合選擇器 4.常用元素屬性 4.1字體屬性 4.2文本屬性 4.3背景屬性 4.4圓角矩形 4.5元素的顯示模式 4…

?LeetCode解法匯總2682. 找出轉圈游戲輸家

目錄鏈接&#xff1a; 力扣編程題-解法匯總_分享記錄-CSDN博客 GitHub同步刷題項目&#xff1a; https://github.com/September26/java-algorithms 原題鏈接&#xff1a; 力扣&#xff08;LeetCode&#xff09;官網 - 全球極客摯愛的技術成長平臺 描述&#xff1a; n 個朋友…

【Leetcode】84.柱狀圖中最大的矩形(Hard)

一、題目 1、題目描述 給定 n n n 個非負整數,用來表示柱狀圖中各個柱子的高度。每個柱子彼此相鄰,且寬度為 1 。 求在該柱狀圖中,能夠勾勒出來的矩形的最大面積。 示例1: 輸入:heights = [2,1,5,6,2,3] 輸出:10 解釋:最大的矩形為圖中紅色區域,面積為 10示例2:…

學習Vue:Vue Router的集成與基本配置

在Vue.js中&#xff0c;路由與導航是構建單頁應用程序&#xff08;SPA&#xff09;的關鍵概念。Vue Router是Vue.js官方提供的路由管理庫&#xff0c;它允許您輕松地實現頁面之間的切換、嵌套路由和參數傳遞。在本文中&#xff0c;我們將深入了解Vue Router的集成和基本配置。 …

Stephen Wolfram:那么…ChatGPT 在做什么,為什么它有效呢?

So … What Is ChatGPT Doing, and Why Does It Work? 那么…ChatGPT在做什么&#xff0c;為什么它有效呢&#xff1f; The basic concept of ChatGPT is at some level rather simple. Start from a huge sample of human-created text from the web, books, etc. Then train…

IDA遠程調試真機app

IDA遠程調試真機app 第一步&#xff1a;啟動 android_server&#xff0c;并修改端口 # 啟動android_server ./android_server -p31928第二步&#xff1a;端口轉發、掛起程序 # 端口轉發adb forward tcp:31928 tcp:31928# 掛起程序 adb shell am start -D -n com.qianyu.antid…

Hyper-V增加橋接網絡設置(其他方式類同)

點擊連接到的服務器&#xff0c;右單擊或者右邊點擊“虛擬交換機管理器” 選擇網絡種類 配置虛擬交換機信息 外部網絡選擇物理機網卡設備

Linux中UDP服務端和客戶端

1 服務端代碼 #include <stdio.h> #include <head.h> #include <sys/types.h> #include <sys/socket.h> #include <arpa/inet.h>#define PORT 6666 //端口號&#xff1a;1024~49191 #define IP "192.168.1.110"//"192.168.122.1…