目錄
學校的班級個數
手推7個班級,答案17?懷疑人生
破案了,應該是6個班。
破案了,原來寫的是?unionxy(a, b, father);
c++ if兩個數同時為正或為負 簡潔寫法
可以用位運算?
c++可以這樣賦值嗎?a=b=2
修改說明:
解釋:
warning: ^ has lower precedence than <; < will be evaluated first [-Wparentheses] 22 | if((p->val-root->val)^(q->val-root->val)<0) | ^~~~~~~~~~~~~~~~~~~~~怎么辦
解釋:
c++函數傳入Vector《int》 在函數里面修改vector可以嗎
1. 按值傳遞(修改不會影響原始向量)
2. 按引用傳遞(修改會影響原始向量)
3. 按常量引用傳遞(如果不需要修改向量)
三目
題目
學校的班級個數
通過數
1696
提交數
3677
難度
中等
顯示標簽
題目描述
現有一個學校,學校中有若干個班級,每個班級中有若干個學生,每個學生只會存在于一個班級中。如果學生A
和學生B
處于一個班級,學生B
和學生C
處于一個班級,那么我們稱學生A
和學生C
也處于一個班級。
現已知學校中共n?個學生(編號為從1
到n
),并給出m?組學生關系(指定兩個學生處于一個班級),問總共有多少個班級。
輸入描述
第一行兩個整數n??、m??(1≤n≤100,1≤m≤100??),分別表示學生個數、學生關系個數;
接下來m?行,每行兩個整數a?和b?(1≤a≤n,1≤b≤n?,?a≠b),表示編號為a
的學生和編號為b
的學生處于一個班級。
輸出描述
輸出一個整數,表示班級個數。
樣例1
輸入
復制
5 3 4 2 1 3 2 5
輸出
復制
2
解釋
編號2
、4
、5
的學生在同一個班級,編號1
、3
的學生在同一個班級,因此共有兩個班級。
手推7個班級,答案17?懷疑人生
不服來戰?
57 46 22 20 20 46 9 22
41 3030 4 42 48 30 5 41 6 29 5050 4 5 1 49 5 41 48 24 56 23 56 21 8 3 9 24 21 12 21 11 49
31 40 10 31 51 13 10 13
45 52
37 2 15 3737 33 26 27 33 26 55 15 55 2727 38 43 5454 2 54 26 54 36
14 19
44 32
破案了,應該是6個班。
答案17是把沒出現的人一人一班。。。
1班
57:1
57:3
57:4
57:5
57:6
57:8
57:9
57:11
57:12
57:20
57:21
57:22
57:23
57:24
57:29
57:30
57:41
57:42
57:46
57:48
57:49
57:50
57:56
57:57
7:7
2班
13:51
13:10
13:13
13:31
13:40
16:16
17:17
18:18
3班
19:19
19:14
25:25
28:28
34:34
4班
32:32
32:44
35:35
5班
38:26
38:2
38:15
38:27
38:33
38:36
38:37
38:38
38:43
38:54
38:55
39:39
47:47
6班
52:45
52:52
53:53
破案了,原來寫的是?unionxy(a, b, father);
因為他編號從1開始,你不減一會數組越界?unionxy(a-1, b-1, father);
-1立馬完美通過
#include<stdio.h>
#include<bits/stdc++.h>
#include<vector>
using namespace std;vector<int> init(int n)
{vector<int> father(n,1);//父親都初始化為自己for(int i=0;i<n;i++)father[i]=i;return father;
}
int findFather(int a,vector<int>& father)
{int x=a;//記錄該節點while(a!=father[a])a=father[a];int f=father[a];//記錄根節點a=x;while(a!=father[a]){int temp = father[a];father[a] = f;a = temp;}//壓縮路徑return f;
}
void unionxy(int a,int b,vector<int>& father)
{//while(a!=father[a])a=father[a];father[findFather(a,father)]=findFather(b,father);findFather(a,father);
}
int main()
{int n,m,a,b,num=0;//cout<<n<<m;scanf("%d %d",&n,&m);
vector<int> father=init(n);for (int j=0;j<m;j++){scanf("%d %d",&a,&b);unionxy(a-1,b-1,father);}for(int i=0;i<n;i++)if(father[i]==i)num++;printf("%d",num);}
c++ if兩個數同時為正或為負 簡潔寫法
ChatGLM
在C++中,要判斷兩個數同時為正或同時為負,可以使用邏輯運算符來實現簡潔的寫法。假設有兩個整數變量?a
?和?b
,可以使用以下代碼:
cpp
復制
if ((a > 0 && b > 0) || (a < 0 && b < 0)) {// 兩個數同時為正或同時為負
}
這段代碼的邏輯是:
(a > 0 && b > 0)
?檢查?a
?和?b
?是否同時為正。(a < 0 && b < 0)
?檢查?a
?和?b
?是否同時為負。||
?運算符表示“或”,即只要滿足其中一個條件,整個條件就為真。
這樣就可以簡潔地判斷兩個數是否同時為正或同時為負。
訪客_c53a24
可以用位運算?
ChatGLM
是的,可以使用位運算來簡潔地判斷兩個數是否同時為正或同時為負。這種方法利用了符號位的概念。在大多數計算機系統中,整數的符號位是最高位,正數的符號位為0,負數的符號位為1。
假設有兩個整數變量 a 和 b,可以使用以下代碼:
c
復制
if (((a ^ b) >= 0)) {// 兩個數同時為正或同時為負
}
解釋:
a ^ b
?是按位異或操作。如果 a 和 b 的符號位相同(即同時為正或同時為負),那么?a ^ b
?的符號位將為0,整個結果將是一個非負數。- 因此,
((a ^ b) >= 0)
?將在 a 和 b 同時為正或同時為負時為真。
這種方法利用了位運算的特性,避免了顯式的條件判斷,從而更加簡潔高效。
訪客_c53a24
c++可以這樣賦值嗎?a=b=2
ChatGLM
在C++中,你可以使用鏈式賦值,即連續給多個變量賦相同的值。所以,a = b = 2
?是合法的,并且會將?2
?賦值給?b
,然后再將?b
?的值賦給?a
。
例如:
cpp
int a, b;
a = b = 2;
std::cout << a << " " << b << std::endl; // 輸出: 2 2
這行代碼的執行順序如下:
b = 2
:將?2
?賦值給?b
。a = b
:將?b
?的值(現在是?2
)賦值給?a
。
因此,a
?和?b
?最終都會被賦值為?2
。
訪客_c53a24
典型數組越界報錯:Line 1122: Char 34: runtime error: addition of unsigned offset to 0x502000000190 overflowed to 0x50200000018c (stl_vector.h) SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/bits/stl_vector.h:1131:34class Solution { public: int search(vector<int>& nums, int target) { int n=nums.size(); int left=-1,right=n-1,x=nums[n-1]; int mid = left+(right-left)/2;int m = nums[mid]; while(left+1<right) { mid = left+(right-left)/2; m = nums[mid]; if(target<=m) { if(target==m){right=mid;break;} if(target<=x&&x<m) left= mid-1;else right=mid; }else {if(target>x&&x>=m) right=mid-1;else left=mid;} } return (right<n&&right>=0&&nums[right]==target)?right:-1; } };
你遇到的錯誤與向量(數組)索引計算時的溢出有關。這通常發生在當你嘗試用一個超出有效范圍的索引去訪問向量中的元素,或者在進行索引相關的算術運算時發生了溢出。
在你的代碼里,問題可能出在?mid
(中間索引)的計算上,或者?left
(左邊界)和?right
(右邊界)這兩個索引的維護上。我們來檢查一下代碼,并進行修改,以確保索引始終在有效的范圍內。
下面是修改后的代碼版本,包含了一些改進,可以更好地處理索引問題:
cpp
復制
#include <vector>
using namespace std;class Solution {
public:int search(vector<int>& nums, int target) {int n = nums.size();if (n == 0) return -1; // 如果數組為空,直接返回-1int left = 0, right = n - 1; // 初始化左邊界為0,右邊界為最后一個元素的索引int x = nums[n - 1]; // 獲取最后一個元素的值(雖然在這個修正版本里暫時用不到,但保留)while (left <= right) { // 循環條件:只要左邊界不越過右邊界就繼續int mid = left + (right - left) / 2; // 計算中間索引,這樣寫可以避免整數溢出int m = nums[mid]; // 獲取中間位置的元素值if (m == target) {return mid; // 如果中間元素正好是目標值,直接返回它的索引} else if (m < target) {left = mid + 1; // 如果中間元素小于目標值,說明目標在右半部分,調整左邊界} else {right = mid - 1; // 如果中間元素大于目標值,說明目標在左半部分,調整右邊界}}return -1; // 如果循環結束都沒找到,返回-1表示目標不在數組中}
};
修改說明:
- 初始檢查:增加了一個檢查,如果傳入的向量是空的(大小為0),直接返回-1,避免后續操作出錯。
- 初始化:將?
left
?初始化為0,right
?初始化為?n - 1
(數組的最后一個有效索引),確保它們一開始就在合法的范圍內。 - 循環條件:將循環條件改為?
left <= right
。這意味著只要?left
?不大于?right
,循環就會繼續。當?left
?最終等于?right + 1
?時,循環結束,表明已經搜索了所有可能的位置。 - Mid 計算:計算?
mid
?的方式改為?left + (right - left) / 2
。這種寫法比?(left + right) / 2
?更安全,因為它先計算?right - left
,這個差值通常比?left + right
?小得多,不容易溢出,尤其是在?left
?和?right
?都很大的時候。 - 比較邏輯:簡化了比較邏輯。直接檢查?
mid
?位置的元素?m
?是否等于?target
。如果不等于,根據?m
?與?target
?的大小關系,將搜索范圍縮小到左半部分或右半部分。
這個修改后的代碼版本應該能正確處理索引,避免你之前遇到的溢出問題。如果你的問題依然存在,請提供更多的上下文信息或者具體的錯誤信息,我會盡力提供進一步的幫助。
訪客_c53a24
/** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode(int x) : val(x), left(NULL), right(NULL) {} * }; */ class Solution { public: TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) { auto dfs=[&](this auto&& dfs,TreeNode* root)-> TreeNode* { if(root==q||root==q||root==NULL)return root; TreeNode* l = dfs(root->left); TreeNode* r = dfs(root->right); if(l!=NULL&&r!=NULL)return root;else return (l!=NULL)? l: r; }; return dfs(root); } };哪里有錯
ChatGLM
你的代碼有幾個小錯誤和可以改進的地方:
-
在?
if(root==q||root==q||root==NULL)
?這一行中,root==q
?出現了兩次,應該是?root==p
?和?root==q
。 -
在?
if(l!=NULL&&r!=NULL)return root;else return (l!=NULL)? l: r;
?這一行中,邏輯可以簡化,因為如果?l
?和?r
?都不為?NULL
,那么?root
?就是最低公共祖先。否則,返回?l
?或?r
?中不為?NULL
?的那個。
以下是修正后的代碼:
cpp
復制
/*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode *left;* TreeNode *right;* TreeNode(int x) : val(x), left(NULL), right(NULL) {}* };*/
class Solution {
public:TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {auto dfs = [&](this auto&& dfs, TreeNode* root) -> TreeNode* {if (root == nullptr) return nullptr;if (root == p || root == q) return root;TreeNode* left = dfs(root->left);TreeNode* right = dfs(root->right);if (left != nullptr && right != nullptr) return root;return left != nullptr ? left : right;};return dfs(root);}
};
解釋:
- 初始檢查:如果?
root
?是?nullptr
,直接返回?nullptr
。 - 找到目標節點:如果?
root
?是?p
?或?q
,返回?root
。 - 遞歸搜索:遞歸搜索左子樹和右子樹。
- 確定最低公共祖先:
- 如果左子樹和右子樹都找到了目標節點,那么當前節點就是最低公共祖先。
- 否則,返回左子樹或右子樹中找到的目標節點。
這樣修改后,代碼邏輯更加清晰,并且能夠正確找到最低公共祖先。
訪客_c53a24
if((p->val-root->val)^(q->val-root->val)<0)
warning: ^ has lower precedence than <; < will be evaluated first [-Wparentheses] 22 | if((p->val-root->val)^(q->val-root->val)<0) | ^~~~~~~~~~~~~~~~~~~~~怎么辦
ChatGLM
這個警告是因為?^
(按位異或)運算符的優先級低于?<
(小于)運算符。為了避免這種歧義,應該使用括號明確表達式的優先級。
在你的代碼中,(p->val - root->val) ^ (q->val - root->val) < 0
?這一行,應該明確?(p->val - root->val)
?和?(q->val - root->val)
?的異或操作優先于?<
?操作。
以下是修正后的代碼:
cpp
if (((p->val - root->val) ^ (q->val - root->val)) < 0)
// 你的代碼邏輯
;
解釋:
- 使用額外的括號?
((p->val - root->val) ^ (q->val - root->val))
?來確保異或操作優先于比較操作。 - 這樣可以避免優先級問題,并且代碼更加清晰。
這樣修改后,編譯器就不會再發出警告,并且代碼的邏輯也更加明確。
訪客_c53a24
c++函數傳入Vector《int》 在函數里面修改vector可以嗎
ChatGLM
是的,在C++中,你可以將一個?std::vector<int>
?傳遞給函數,并在函數內部修改它。默認情況下,如果你直接傳遞?std::vector<int>
,它是按值傳遞的,這意味著函數內部會創建一個該向量的副本,對副本的修改不會影響原始向量。
如果你想在函數內部修改原始向量,你可以使用引用傳遞。以下是兩種方法:
1. 按值傳遞(修改不會影響原始向量)
cpp
復制
#include <vector>
#include <iostream>void modifyVector(std::vector<int> vec) {vec.push_back(4); // 修改的是副本
}int main() {std::vector<int> myVector = {1, 2, 3};modifyVector(myVector);// myVector 仍然是 {1, 2, 3}for (int num : myVector) {std::cout << num << " ";}return 0;
}
2. 按引用傳遞(修改會影響原始向量)
cpp
復制
#include <vector>
#include <iostream>void modifyVector(std::vector<int>& vec) {vec.push_back(4); // 修改的是原始向量
}int main() {std::vector<int> myVector = {1, 2, 3};modifyVector(myVector);// myVector 現在是 {1, 2, 3, 4}for (int num : myVector) {std::cout << num << " ";}return 0;
}
3. 按常量引用傳遞(如果不需要修改向量)
如果你只是想在函數內部讀取向量,而不需要修改它,可以使用常量引用傳遞:
cpp
復制
#include <vector>
#include <iostream>void printVector(const std::vector<int>& vec) {for (int num : vec) {std::cout << num << " ";}std::cout << std::endl;
}int main() {std::vector<int> myVector = {1, 2, 3};printVector(myVector);// myVector 仍然是 {1, 2, 3}return 0;
}
引用
總結:
- 按值傳遞:函數內部修改的是副本,不影響原始向量。
- 按引用傳遞:函數內部修改的是原始向量。
- 按常量引用傳遞:函數內部只能讀取向量,不能修改。
根據你的需求選擇合適的方式傳遞向量。
三目
偶會報錯
cout << (findFather(k, father) == findFather(j, father)) ? "Yes" : "No" << endl;
解決方法是加個括號?
cout << ((findFather(k, father) == findFather(j, father)) ? "Yes" : "No" )<< endl;