vector容器(詳解)

本文最后是模擬實現全部講解,文章穿插有彩色字體,是我總結的技巧和關鍵

?1.vector的介紹及使用

1.1 vector的介紹

https://cplusplus.com/reference/vector/vector/(vector的介紹)

了解

1. vector是表示可變大小數組的序列容器。

2. 就像數組一樣,vector也采用的連續存儲空間來存儲元素。也就是意味著可以采用下標方括號[]對vector的元素進行訪問,和數組一樣高效。但是又不像數組,它的大小是可以動態改變的,而且它的大小會被容器自動處理。

3. 本質講,vector使用動態分配數組來存儲它的元素。當新元素插入時候,這個數組需要被重新分配大小為了增加存儲空間。其做法是,分配一個新的數組,然后將全部元素移到這個數組。就時間而言,這是一個相對代價高的任務,因為每當一個新的元素加入到容器的時候,vector并不會每次都重新分配大小。

使用STL的三個境界:能用,明理,能擴展 ,那么下面學習vector,我們也是按照這個方法去學習

1.2 vector的使用

vector學習時一定要學會查看文檔:https://cplusplus.com/reference/vector/vector,vector在實際中非常的重要,在實際中我們熟悉常見的接口就可以,下面列出了哪些接口是要重點掌握的

1.2.1 vector的定義

defb6493048044e1b6ea4b32c7f3b9cd.png

1.2.2 vector iterator 的使用

8e1515922f374f87962a7ce72563d2f7.png

d364ec0bf21c4d9f932f3c2ea3caf4ec.png

0e6f2da33ec844598e52cef529e4acec.png

1.2.3 vector 空間增長問題

3f79852cb8704d0e918fc501a2c08fc2.png

capacity的代碼在vs和g++下分別運行會發現,vscapacity是按1.5倍增長的,g++是按2倍增長的

這個問題經常會考察,不要固化的認為,vector增容都是2倍,具體增長多少是根據具體的需求定義的。vs是PJ版本STL,g++是SGI版本STL。

reserve只負責開辟空間,如果確定知道需要用多少空間,reserve可以緩解vector增容的代價缺陷問題。resize在開空間的同時還會進行初始化,影響size

// 如果已經確定vector中要存儲元素大概個數,可以提前將空間設置足夠
// 就可以避免邊插入邊擴容導致效率低下的問題了
void TestVector()
{vector<int> v;size_t sz = v.capacity();v.reserve(100); // 提前將容量設置好,可以避免一遍插入一遍擴容cout << "making bar grow:\n";for (int i = 0; i < 100; ++i) {v.push_back(i);if (sz != v.capacity()){sz = v.capacity();cout << "capacity changed: " << sz << '\n';}}
}

1.2.3 vector 增刪查改

3138f5be121b4a97a90ecb8eac1bd91c.png

1.2.4 vector 迭代器失效問題。(重點)

迭代器失效解決辦法:在使用前,對迭代器重新賦值即可

? ? ? 迭代器的主要作用就是讓算法能夠不用關心底層數據結構,其底層實際就是一個指針,或者是對指針進行了封裝,比如:vector的迭代器就是原生態指針T* 。因此迭代器失效,實際就是迭代器底層對應指針所指向的空間被銷毀了,而使用一塊已經被釋放的空間,造成的后果是程序崩潰(即如果繼續使用已經失效的迭代器,程序可能會崩潰)。

對于vector可能會導致其迭代器失效的操作有:

1. 會引起其底層空間改變的操作,都有可能是迭代器失效,比如:resize、reserve、insert、assign。push_back等。

#include <iostream>
using namespace std;
#include <vector>
int main()
{vector<int> v={1,2,3,4,5,6};auto it = v.begin();// 將有效元素個數增加到100個,多出的位置使用8填充,操作期間底層會擴容v.resize(100, 8);// reserve的作用就是改變擴容大小但不改變有效元素個數,操作期間可能會引起底層容量改變v.reserve(100);// 插入元素期間,可能會引起擴容,而導致原空間被釋放v.insert(v.begin(), 0);v.push_back(8);// 給vector重新賦值,可能會引起底層容量改變v.assign(100, 8);/*出錯原因:以上操作,都有可能會導致vector擴容,也就是說vector底層原理舊空間被釋放掉,
而在打印時,it還使用的是釋放之間的舊空間,在對it迭代器操作時,實際操作的是一塊已經被釋放的
空間,而引起代碼運行時崩潰。解決方式:在以上操作完成之后,如果想要繼續通過迭代器操作vector中的元素,只需給it重新
賦值即可。*/while(it != v.end()){cout<< *it << " " ;++it;}cout<<endl;return 0;
}

結論:insert和erase形參pos都可能會失效(就當他失效了),所以原則上insert和erase過的迭代器不要使用

9ce49e53fb21403bae49aecf68b17660.png

我們發現庫里邊的erase返回值是一個迭代器,將返回值拷貝給外部定義的it可以保證迭代器不失效,為什么會有失效的可能性呢?-》刪除數據后可能會異地縮容,返回的pos指針依舊指向被釋放過的區域,一定是不對的

22f3f1ffebf14a3b80784e966d49bfbc.png

比如下邊的我們調用庫里邊的vector,erase后沒有給迭代器賦值,出現了報錯

		// 迭代器失效void test_vector6(){std::vector<int> v;v.push_back(1);v.push_back(2);v.push_back(4);v.push_back(4);v.push_back(4);v.push_back(6);for (auto e : v){cout << e << " ";}cout << endl;// 要求刪除所有的偶數std::vector<int>::iterator it = v.begin();while (it != v.end()){if (*it % 2 == 0){v.erase(it);}else{++it;}}for (auto e : v){cout << e << " ";}cout << endl;}

f686458c1c684293b8642b10738d669b.png

當我們將迭代器賦值過后,就順利運行了

bae897c01258435882dc697d7029a74d.png

insert后迭代器失效和erase是一個道理,就不再贅述了。

就記住insert/erase后的迭代器重新賦值后再用

2.vector深度剖析及模擬實現

使用memcpy拷貝問題(memmove同理,要將模擬實現里用到這兩個淺拷貝的都換成賦值拷貝,因為自定義類型使用這兩個函數會淺拷貝,要賦值拷貝-》深拷貝才能防止同一塊空間析構兩次的風險)

假設模擬實現的vector中的reserve接口中,使用memcpy進行的拷貝,以下代碼會發生什么問題?

int main()
{bite::vector<bite::string> v;v.push_back("1111");v.push_back("2222");v.push_back("3333");return 0;
}

問題分析:

1. memcpy是內存的二進制格式拷貝,將一段內存空間中內容原封不動的拷貝到另外一段內存空間中

2. 如果拷貝的是自定義類型的元素,memcpy既高效又不會出錯,但如果拷貝的是自定義類型元素,并且自定義類型元素中涉及到資源管理時,就會出錯,因為memcpy的拷貝實際是淺拷貝

9bbd212f6d5b47dcaa010473f747145b.png

b7810f4389e94331b3c68be36952206f.png

d695ab9522cc4b0e92f7c98df1046717.png

3c1ed11209e7475aa7db935163f5ebde.png

結論:如果對象中涉及到資源管理時,千萬不能使用memcpy進行對象之間的拷貝,因為memcpy淺拷貝,否則可能會引起內存泄漏甚至程序崩潰。(要調用賦值拷貝深拷貝)

動態二維數組理解

這里力扣有一道題,可以搜一下楊輝三角,就是用vector寫的

// 以楊慧三角的前n行為例:假設n為5
void test2vector(size_t n)
{// 使用vector定義二維數組vv,vv中的每個元素都是vector<int>vector<vector<int>> vv(n);// 將二維數組每一行中的vecotr<int>中的元素全部設置為1for (size_t i = 0; i < n; ++i)vv[i].resize(i + 1, 1);// 給楊慧三角出第一列和對角線的所有元素賦值for (int i = 2; i < n; ++i){for (int j = 1; j < i; ++j){vv[i][j] = vv[i - 1][j] + vv[i - 1][j - 1];}}
}

vector<vector<int>> vv(n);

構造一個vv動態二維數組,vv中總共有n個元素,每個元素都是vector類型的,每行沒有包含任何元素,如果n為5時如下所示:

fd7c35993c5a4b01ad8089daa7e5b69b.png

vv中元素填充完成之后,如下圖所示:

a03e7e083b3a40f583545c0731ca793d.png

vector模擬實現全部代碼

vector.h

#include<assert.h>namespace jzy
{template<class T>class vector{public:typedef T* iterator;typedef const T* const_iterator;vector(){}/*vector(const vector<T>& v){_start = new T[v.capacity()];memcpy(_start, v._start, v.size()* sizeof(T));_finish = _start + v.size();_endofstorage = _start + v.capacity();}*/// v2(v1)vector(const vector<T>& v){reserve(v.capacity());for (const auto& e : v){push_back(e);}}template <class InputIterator>vector(InputIterator first, InputIterator last){while (first != last){push_back(*first);++first;}}vector(size_t n, const T& val = T()){resize(n, val);}vector(int n, const T& val = T()){resize(n, val);}// 21:06void swap(vector<T>& v){std::swap(_start, v._start);std::swap(_finish, v._finish);std::swap(_endofstorage, v._endofstorage);}// v1 = v3vector<T>& operator=(vector<T> v){swap(v);return *this;}~vector(){if (_start){delete[] _start;_start = _finish = _endofstorage = nullptr;}}iterator begin(){return _start;}iterator end(){return _finish;}const_iterator begin() const{return _start;}const_iterator end() const{return _finish;}// 20: 10繼續void reserve(size_t n){if (n > capacity()){size_t old = size();T* tmp = new T[n];if (_start){//memcpy(tmp, _start, old * sizeof(T));for (size_t i = 0; i < old; i++){tmp[i] = _start[i];}delete[] _start;}_start = tmp;_finish = _start + old;_endofstorage = _start + n;}}void resize(size_t n, T val = T()){if (n > size()){reserve(n);while (_finish < _start + n){*_finish = val;++_finish;}}else{_finish = _start + n;}}void push_back(const T& x){if (_finish == _endofstorage){size_t newcapacity = capacity() == 0 ? 4 : capacity() * 2;reserve(newcapacity);}*_finish = x;++_finish;}void pop_back(){assert(size() > 0);--_finish;}iterator insert(iterator pos, const T& x){assert(pos >= _start && pos <= _finish);if (_finish == _endofstorage){size_t len = pos - _start;reserve(capacity() == 0 ? 4 : capacity() * 2);pos = _start + len;//這里發生內部的迭代器失效,需要重新賦值}//memmove(pos + 1, pos, sizeof(T) * (_finish - pos));iterator end = _finish - 1;while (end >= pos){*(end + 1) = *end;--end;}*pos = x;++_finish;return pos;}iterator erase(iterator pos){assert(pos >= _start);assert(pos < _finish);iterator it = pos + 1;while (it < _finish){*(it - 1) = *it;++it;}_finish--;return pos;}size_t size() const{return _finish - _start;}size_t capacity() const{return _endofstorage - _start;}T& operator[](size_t pos){assert(pos < size());return _start[pos];}const T& operator[](size_t pos) const{assert(pos < size());return _start[pos];}private:iterator _start = nullptr;iterator _finish = nullptr;iterator _endofstorage = nullptr;};void print_vector(const vector<int>& v){for (auto e : v){cout << e << " ";}cout << endl;}}

test.cpp

#include<iostream>
using namespace std;
#include<string>
#include<vector>
#include<algorithm>
#include<list>
#include"vector.h"namespace jzy
{void test_vector1(){vector<int> v;v.push_back(1);v.push_back(2);v.push_back(3);v.push_back(4);v.push_back(4);v.push_back(4);v.push_back(4);vector<int>::iterator it = v.begin();while (it != v.end()){cout << *it << " ";++it;}cout << endl;for (auto e : v){cout << e << " ";}cout << endl;v[0]++;for (size_t i = 0; i < v.size(); i++){cout << v[i] << " ";}cout << endl;v.insert(v.begin(), 100);print_vector(v);v.insert(v.begin(), 100);print_vector(v);int i = 0;int j = int();int k = int(10);}void test_vector2(){vector<int> v;v.push_back(1);v.push_back(2);v.push_back(3);v.push_back(4);v.push_back(4);v.push_back(4);vector<int> v1 = v;for (auto e : v){cout << e << " ";}cout << endl;for (auto e : v1){cout << e << " ";}cout << endl;vector<int> v2;v2.push_back(11);v2.push_back(21);v2.push_back(31);v2.push_back(411);v2.push_back(41);v2.push_back(41);v1 = v2;for (auto e : v1){cout << e << " ";}cout << endl;for (auto e : v2){cout << e << " ";}cout << endl;}void test_vector3(){vector<int> v;v.reserve(10);v.push_back(1);v.push_back(2);v.push_back(3);v.push_back(4);v.push_back(5);v.push_back(6);for (auto e : v){cout << e << " ";}cout << endl;v.resize(8);for (auto e : v){cout << e << " ";}cout << endl;v.resize(15, 1);for (auto e : v){cout << e << " ";}cout << endl;v.resize(3);for (auto e : v){cout << e << " ";}cout << endl;}void test_vector4(){vector<string> v;v.reserve(10);v.push_back("xxxx");v.push_back("xxxx");v.push_back("xxxx");v.push_back("xxxx");v.push_back("xxxx");v.push_back("xxxx");for (auto e : v){cout << e << " ";}cout << endl;v.resize(8);for (auto e : v){cout << e << " ";}cout << endl;v.resize(15, "yyyy");for (auto e : v){cout << e << " ";}cout << endl;v.resize(3);for (auto e : v){cout << e << " ";}cout << endl;}void test_vector5(){vector<int> v;v.push_back(1);v.push_back(2);v.push_back(3);v.push_back(4);v.push_back(5);v.push_back(6);for (auto e : v){cout << e << " ";}cout << endl;v.erase(v.begin() + 3);for (auto e : v){cout << e << " ";}cout << endl;}// 迭代器失效void test_vector6(){std::vector<int> v;v.push_back(1);v.push_back(2);v.push_back(4);v.push_back(4);v.push_back(4);v.push_back(6);for (auto e : v){cout << e << " ";}cout << endl;// 要求刪除所有的偶數std::vector<int>::iterator it = v.begin();while (it != v.end()){if (*it % 2 == 0){it = v.erase(it);}else{++it;}}for (auto e : v){cout << e << " ";}cout << endl;}void test_vector7(){vector<int> v;v.push_back(1);v.push_back(2);v.push_back(3);v.push_back(4);v.push_back(5);v.push_back(6);v.push_back(7);v.push_back(8);v.push_back(9);for (auto e : v){cout << e << " ";}cout << endl;vector<string> vstr;vstr.push_back("1111");vstr.push_back("1111");vstr.push_back("1111");vstr.push_back("1111");vstr.push_back("1111");for (auto e : vstr){cout << e << " ";}cout << endl;}void test_vector8(){/*vector<int> v1;v1.push_back(1);v1.push_back(2);v1.push_back(3);v1.push_back(4);v1.push_back(5);vector<int> v2(v1.begin(), v1.end());for (auto e : v2){cout << e << " ";}cout << endl;list<int> lt;lt.push_back(10);lt.push_back(20);lt.push_back(30);lt.push_back(40);vector<int> v3(lt.begin(), lt.end());for (auto e : v3){cout << e << " ";}cout << endl;int a[] = { 100, 200, 300 };vector<int> v4(a, a+3);for (auto e : v4){cout << e << " ";}cout << endl;*/}void test_vector9(){vector<string> v1(5, "1111");for (auto e : v1){cout << e << " ";}cout << endl;vector<int> v2(5, 1);for (auto e : v2){cout << e << " ";}cout << endl;}
}int main()
{jzy::test_vector6();return 0;
}

3.vector oj題

136. 只出現一次的數字 - 力扣(LeetCode)

118. 楊輝三角 - 力扣(LeetCode)

26. 刪除有序數組中的重復項 - 力扣(LeetCode)

137. 只出現一次的數字 II - 力扣(LeetCode)

260. 只出現一次的數字 III - 力扣(LeetCode)

數組中出現次數超過一半的數字_牛客題霸_牛客網

17. 電話號碼的字母組合 - 力扣(LeetCode)

vector模擬實現過程詳解

這里迭代器很簡單,就是將類型重命名為iterator

const迭代器命名為const T*,意思是指針指向的對象不可修改

無參構造函數很簡單,c++11缺省值,初始化列表會用聲明處的缺省值,這三個指針為空就夠了(vector底層就是三個指針維護的,起始指針_start,有效字符結尾_finish,容量結尾_endofstorage)

拷貝構造,直接reserve擴容開空間,然后用范圍for將v1的內容給給e,再尾插到v2,完成拷貝構造

用區間構造,類型比較長是為了和庫里邊一樣,當迭代器指針不指向有效數據的下一個,尾插,迭代器++,完成構造

用n個val構造,不傳val是會初始化為默認構造

這里是防止調用歧義,當用n個整數初始化vector時,可能會調用迭代器區間構造,這個是為了防止調用歧義

交換邏輯,和string一樣,交換內置類型

賦值拷貝,v3先拷貝構造一個v,用v和v1交換三個指針,v1維護的就是v3的值,而且局部對象出作用域會調用析構,將v析構,剛好只剩v1和v3

析構函數,當指針指向非空,釋放空間并且置空

迭代器和const迭代器,很簡單,非const類型調用非const,返回非const可修改,const類型調用const迭代器,返回const對象,不可修改

reserve擴容邏輯,參數是要擴容的大小,只擴容不縮容。

要定義一個old保存舊size()是為了后邊賦值會改變_start,size()兩個隨機地址相減肯定錯,申請新空間,當原數組非空的時候,將舊空間的數據(自定義類型賦值拷貝)拷貝到新空間,并且釋放舊空間(如果是自定義類型會調用它的析構),最后賦值新的_start,_finish,和_endofstorage(注意這個要深拷貝,防止同一塊空間析構兩次)

只給數字,val是默認構造,也可以給數字和初始值

如果n大于size和capacity,擴容+尾插

如果n大于size,小于capacity,只尾插不擴容

如果n小于size,會將_finish設置為有效數據個數,不擴容

尾插,檢查擴容+尾插

尾刪,檢查size大于0,--finish

插入邏輯是先讓end指向最后一個數據的前一個,從右向左依次向后挪動數據,直到pos位置結束,然后再插入,尾插直接不會進入循環

插入,檢查擴容(如果擴容會開辟新空間,pos指向原來空間,需要重新賦值防止迭代器失效),下邊就是正常的挪動數據邏輯并且插入(不能用memmove因為會淺拷貝,造成兩次析構同一塊空間,要賦值拷貝進行深拷貝才行)

刪除,因為_finish下標是有效數據的下一個,所以刪除不能pos等于finish,定義it是要刪除的下一個,刪除是挪動覆蓋,it++直到finish結束

size和capacity都很簡單,size是有效數據個數,結尾指針減去起始指針

capacity是容量,容量指針減去起始指針

要斷言檢查越界,非const調用非const,返回可修改的引用,const調用const,返回const&不可修改

對應測試樣例

可以看到尾插+擴容,并且插入迭代器位置和數字,插入結果也很清楚

拷貝構造和賦值拷貝,結果跟我們預料的一樣

可以看到,正常打印的結果

當resize的值大于size小于capacity時,只尾插不擴容

大于capacity時,擴容+尾插

小于size,刪除數據,容量不變

這個和上邊差不多,無非存儲的數據換成string,(注意,string默認構造是空串,沒有傳參數時是構造空串)

刪除很簡單,就是刪除某個位置的元素,傳對應的指針過去

迭代器失效,很簡單,記住insert或者erase后的迭代器記得接收一下就行

這是很常規的尾插數字和字符串,注意尾插字符串時會先構造一個臨時string對象,然后賦值拷貝給vector對應位置的string對象

典型的用迭代器區間構造,不管是vector,list,還是原生數組指針都可以構造

用數字和參數構造,不傳參默認是這個類型的默認構造,比如string、默認構造是空字符串,int默認構造是0

感謝觀看,有不全面的地方希望大佬們交流,歡迎交流

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

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

相關文章

Ubuntu 下 nginx-1.24.0 源碼分析 ngx_debug_init();

目錄 ngx_debug_init() 函數&#xff1a; NGX_LINUX 的定義&#xff1a; ngx_debug_init() 函數&#xff1a; ngx_debug_init() 函數定義在 src\os\unix 目錄下的 ngx_linux_config.h 中 #define ngx_debug_init() 也就是說這個環境下的 main 函數中的 ngx_debug_init() 這…

Airflow:深入理解Apache Airflow Task

Apache Airflow是一個開源工作流管理平臺&#xff0c;支持以編程方式編寫、調度和監控工作流。由于其靈活性、可擴展性和強大的社區支持&#xff0c;它已迅速成為編排復雜數據管道的首選工具。在這篇博文中&#xff0c;我們將深入研究Apache Airflow 中的任務概念&#xff0c;探…

開發環境搭建-4:WSL 配置 docker 運行環境

在 WSL 環境中構建&#xff1a;WSL2 (2.3.26.0) Oracle Linux 8.7 官方鏡像 基本概念說明 容器技術 利用 Linux 系統的 文件系統&#xff08;UnionFS&#xff09;、命名空間&#xff08;namespace&#xff09;、權限管理&#xff08;cgroup&#xff09;&#xff0c;虛擬出一…

JavaScript 基礎 - 7

關于JS函數部分的學習和一個案例的練習 1 函數封裝 抽取相同部分代碼封裝 優點 提高代碼復用性&#xff1a;封裝好的函數可以在多個地方被重復調用&#xff0c;避免了重復編寫相同的代碼。例如&#xff0c;編寫一個計算兩個數之和的函數&#xff0c;在多個不同的計算場景中都…

詳解u3d之AssetBundle

一.AssetBundle的概念 “AssetBundle”可以指兩種不同但相關的東西。 1.1 AssetBundle指的是u3d在磁盤上生成的存放資源的目錄 目錄包含兩種類型文件(下文簡稱AB包)&#xff1a; 一個序列化文件&#xff0c;其中包含分解為各個對象并寫入此單個文件的資源。資源文件&#x…

微信登錄模塊封裝

文章目錄 1.資質申請2.combinations-wx-login-starter1.目錄結構2.pom.xml 引入okhttp依賴3.WxLoginProperties.java 屬性配置4.WxLoginUtil.java 后端通過 code 獲取 access_token的工具類5.WxLoginAutoConfiguration.java 自動配置類6.spring.factories 激活自動配置類 3.com…

DeepSeek 介紹及對外國的影響

DeepSeek 簡介 DeepSeek&#xff08;深度求索&#xff09;是一家專注實現 AGI&#xff08;人工通用智能&#xff09;的中國科技公司&#xff0c;2023 年成立&#xff0c;總部位于杭州&#xff0c;在北京設有研發中心。與多數聚焦具體應用&#xff08;如人臉識別、語音助手&…

MySQL數據庫(二)- SQL

目錄 ?編輯 一 DDL (一 數據庫操作 1 查詢-數據庫&#xff08;所有/當前&#xff09; 2 創建-數據庫 3 刪除-數據庫 4 使用-數據庫 (二 表操作 1 創建-表結構 2 查詢-所有表結構名稱 3 查詢-表結構內容 4 查詢-建表語句 5 添加-字段名數據類型 6 修改-字段數據類…

ARM嵌入式學習--第十天(UART)

--UART介紹 UART(Universal Asynchonous Receiver and Transmitter)通用異步接收器&#xff0c;是一種通用串行數據總線&#xff0c;用于異步通信。該總線雙向通信&#xff0c;可以實現全雙工傳輸和接收。在嵌入式設計中&#xff0c;UART用來與PC進行通信&#xff0c;包括與監控…

面試題-消失的數字-異或

消失的數字 數組nums包含從0到n的所有整數&#xff0c;但其中缺了一個。請編寫代碼找出那個缺失的整數。你有辦法在 O(n) 時間內完成嗎&#xff1f; 示例&#xff1a; 輸入&#xff1a;[3,0,1] 輸出&#xff1a;2 int missingNumber(int* nums, int numsSize) {}分析 本題對…

數據結構與算法之棧: LeetCode 1685. 有序數組中差絕對值之和 (Ts版)

有序數組中差絕對值之和 https://leetcode.cn/problems/sum-of-absolute-differences-in-a-sorted-array/description/ 描述 給你一個 非遞減 有序整數數組 nums 請你建立并返回一個整數數組 result&#xff0c;它跟 nums 長度相同&#xff0c;且result[i] 等于 nums[i] 與數…

筆試-排列組合

應用 一個長度為[1, 50]、元素都是字符串的非空數組&#xff0c;每個字符串的長度為[1, 30]&#xff0c;代表非負整數&#xff0c;元素可以以“0”開頭。例如&#xff1a;[“13”, “045”&#xff0c;“09”&#xff0c;“56”]。 將所有字符串排列組合&#xff0c;拼起來組成…

Python3 OS模塊中的文件/目錄方法說明十七

一. 簡介 前面文章簡單學習了 Python3 中 OS模塊中的文件/目錄的部分函數。 本文繼續來學習 OS 模塊中文件、目錄的操作方法&#xff1a;os.walk() 方法、os.write()方法 二. Python3 OS模塊中的文件/目錄方法 1. os.walk() 方法 os.walk() 方法用于生成目錄樹中的文件名&a…

[Java]抽象類

1. 什么是抽象類&#xff1f; 1.1 定義&#xff1a; 抽象類是一個不能實例化的類&#xff0c;它是用來作為其他類的基類的。抽象類可以包含抽象方法和非抽象方法。抽象方法沒有方法體&#xff0c;子類必須重寫這些方法并提供具體的實現。抽象類可以有構造方法、成員變量、靜態…

css三角圖標

案例三角&#xff1a; <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Document</title><s…

跨越通信障礙:深入了解ZeroMQ的魅力

在復雜的分布式系統開發中&#xff0c;進程間通信就像一座橋梁&#xff0c;連接著各個獨立運行的進程&#xff0c;讓它們能夠協同工作。然而&#xff0c;傳統的通信方式往往伴隨著復雜的設置、高昂的性能開銷以及有限的靈活性&#xff0c;成為了開發者們前進道路上的 “絆腳石”…

深入解析 COUNT(DISTINCT) OVER(ORDER BY):原理、問題與高效替代方案

目錄 一、累計去重需求場景 二、COUNT(DISTINCT) OVER(ORDER BY) 語法解析 2.1 基礎語法 2.2 執行原理 三、三大核心問題分析

線性數據結構:單向鏈表

放棄眼高手低&#xff0c;你真正投入學習&#xff0c;會因為找到一個新方法產生成就感&#xff0c;學習不僅是片面的記單詞、學高數......只要是提升自己的過程&#xff0c;探索到了未知&#xff0c;就是學習。 目錄 一.鏈表的理解 二.鏈表的分類&#xff08;重點理解&#xf…

基于PyQt5打造的實用工具——PDF文件加圖片水印,可調大小位置,可批量處理!

01 項目簡介 &#xff08;1&#xff09;項目背景 隨著PDF文件在信息交流中的廣泛應用&#xff0c;用戶對圖片水印的添加提出了更高要求&#xff0c;既要美觀&#xff0c;又需高效處理批量文件。現有工具難以實現精確調整和快速批量操作&#xff0c;操作繁瑣且效果不理想。本項…

MCU內部ADC模塊誤差如何校準

本文章是筆者整理的備忘筆記。希望在幫助自己溫習避免遺忘的同時&#xff0c;也能幫助其他需要參考的朋友。如有謬誤&#xff0c;歡迎大家進行指正。 一、ADC誤差校準引言 MCU 片內 ADC 模塊的誤差總包括了 5 個靜態參數 (靜態失調&#xff0c;增益誤差&#xff0c;微分非線性…