九日集訓 Day 2 迴圈
一、概念定義
對於迴圈來說,C/C++ 語言中總共有兩種結構,while 和 for,但是對於刷題來說,其實兩者沒有本質區別,所以這裡我只介紹相對較為簡單的 for 語句。
1、語法規則
for 語句的一般形式為:
for(迴圈初始化表示式; 迴圈條件表示式; 迴圈執行表示式){
迴圈體
}
它的執行過程為:
1)首先,執行 迴圈初始化表示式;
2)然後,執行 迴圈條件表示式,如果它的值為真,則執行迴圈體,否則結束迴圈;
3)接著,執行完迴圈體後再執行 迴圈執行表示式;
4)重複執行步驟 2)和 3),直到 迴圈條件表示式 的值為假,則結束迴圈。
上面的步驟中,2)和 3)是一次迴圈,會重複執行,for 語句的主要作用就是不斷執行步驟 2)和 3)。執行過程如下圖所示:
細心的讀者可能會發現,迴圈體 和 迴圈執行表示式 其實是可以合併的,是的,的確是這樣。在下面的例子中我會講到。
2、簡單應用
接下來,我們就來實現一個最簡單的迴圈語句,求 1 + 2 + 3 + ... + n 的值。
int sumNums(int n){
int i;
int sum=0;
for(int i=1;i<=n;i++){
sum += i;
}
return sum;
}
- 這是一個函式,傳參是 n,返回值為 1 + 2 + 3 + ... + n 的值;
- 作為一個迴圈變數;
- 初始化求和的值 s 為 0;
- for 語句三部分:迴圈初始化表示式:i = 1;迴圈條件表示式:i <= n;迴圈執行表示式:++i;
- 迴圈體:sum += i;,表示將 1、2、3、4、... 累加到 sum上;
- 返回求和sum的值;
以上這段程式碼,實現了一個數學上的 等差數列 求和。也可以用公式來表示,如下:
而利用 for 迴圈,讓我們拋開了數學思維,用程式的角度來實現數學問題。注意,for 迴圈中的那個表示式都可以省略,但它們之間的 分號 必須保留。
3、初始化表示式
1)初始化表示式外接
我們可以把 初始化表示式 提到 for 迴圈外面,如下:
int i=1;
int sum=0;
for(;i<=n;i++){
sum += i;
}
2)初始化表示式內建
我們也可以把需要的初始化資訊,都在初始化表示式內進行賦值,並且用逗號進行分隔,如下:
int i,sum;
for(int i=1,sum=0;i<=n;i++){
sum += i;
}
4、條件表示式
如果省略 條件表示式,那就代表這個迴圈是一個死迴圈,如下:
int i;
int sum=0;
for(int i=1;;i++){
sum += i;
}
這段程式碼表示這個迴圈沒有結束條件,那自然就不會結束了,編碼過程中應該儘量避免(當然,某些情況下還是需要的,例如遊戲開發中的主迴圈),或者,函式內部有能夠跳出函式的方法,比如 break 關鍵字。
5、執行表示式
執行表示式的作用是 讓迴圈條件 逐漸 不成立,從而跳出迴圈。 當然,它也是可以省略的,因為 迴圈體本身也是一個 語句塊,也可以達到類似功能,如下程式碼所示:
int i,sum=0;
for(i=1;i<=n;i++){
sum += i;
i++;
}
這段程式碼同樣達到了求和的功能,因為執行表示式被放入了迴圈體,這也正是上文所說的迴圈體和迴圈執行表示式合併的問題。
二、題目分析
1、2 的 冪
實現一個函式isPowerOfTwo,判斷一個 32位整型 是否是 2 的冪。
bool isPowerOfTwo(int n){
int i;
unsigned int k=1;
if(n<=0) return false;
if(n==1) return true;
for(i=1;i<=21;i++){
k *= 2;
if(k==n) return true;
}
return false;
}
- (1) 定義一個無符號整型 ;
- (2) 如果 n ≤ 0,則必然不是 2 的冪;
- (3) 1 必然是 2 的 0 次冪;
- (4) 列舉所有 2 的冪 2、4、8、16、... ;
- (5) 一旦找到一個和 相等,返回true,則說明它是 2 的冪;
- (6) 最後,沒有找到的話,返回false表示不是 2 的冪;
2、3 的冪
實現一個函式isPowerOfThree,判斷一個 32位整型 是否是 3 的冪。
bool isPowerOfThree(int n){
int i;
unsigned int k=1;
if(n<=0) return false;
if(n==1) return true;
for(i=1;i<=20;i++){
k *= 3;
if(k==n) return true;
}
return false;
}
和 2的冪 那一題相比,只改了兩個地方:
- (1) 第一個是列舉的上限只需要到 20,因為 3 的 21 次冪超過 32位 整型的上限了;
- (2) 第二個是每次列舉的是 1、3、9、27、...,所以 不斷乘 3。
3、4 的冪
實現一個函式isPowerOfFour,判斷一個 32位整型 是否是 4 的冪。
bool isPowerOfFour(int n){
int i;
unsigned int k=1;
if(n<=0) return false;
if(n==1) return true;
for(i=1;i<=15;i++){
k *= 4;
if(k==n) return true;
}
return false;
}
和 3的冪 那一題相比,只改了兩個地方:
- (1) 第一個是列舉的上限只需要到 15,因為 4 的 16 次 超過 32位 整型的上限了;
- (2) 第二個是每次列舉的是 1、4、16、...,所以 k 不斷乘 4。
4、n 的第 k 個因子
給你兩個正整數n 和k 。如果正整數 i滿足 n % i == 0,那麼我們就說正整數 i是整數 n的因子。考慮整數 n的所有因子,將它們 升序排列 。請你返回第 k個因子。如果 的因子數少於 k,請你返回-1 。
int kthFactor(int n,int k){
int i;
int cnt=0;
for(i=1;i<=n;i++){
if(n%i==0){
cnt++;
if(cnt==k) return i;
}
}
return -1;
}
- (1) 定義一個計數器cnt,初始化為 0;
- (2) 列舉所有範圍在 [1, n] 的數,因為只有這些數才可能是 的因子;
- (3) 一旦滿足 n % i == 0,則計數器加一;
- (4) 當計數器等於 k,則代表找到了 第 k 個因子,直接返回即可;
- (5) 如果一直沒有找到,則表示不存在 第 k 個因子,返回 -1;
5、有效的完全平方數
給定一個 正整數 ,編寫一個函式,如果 是一個完全平方數,則返回true,否則返回 false。
int isPerfectSquare(int x){
int i;
long long p;
for(i=1;;i++){
p = (long long)i*i;
if(p==x) return true;
if(p>x) return false;
}
return false;
}
- (1) 定義一個死迴圈,列舉所有數;
- (2) 列舉所有數的平方,並且注意用 long long 避免 32整型溢位;
- (3) 如果發現某個數的平方正好等於 x,則直接返回true;
- (4) 如果發現列舉的數已經大於 x,無須再往下列舉,直接返回false;
- (5) 這段程式碼是保底,理論上不可能跑到;
三、課後習題
1、求1+2+…+n
求
1+2+...+n
,要求不能使用乘除法、for、while、if、else、switch、case等關鍵字及條件判斷語句(A?B:C)。
class Solution {
public:
int sumNums(int n) {
long long sum=0; //記得開long long防止超時
for(int i=1;i<=n;i++){
sum += i;
}
return sum;
}
};
2、2 的冪
給你一個整數 n,請你判斷該整數是否是 2 的冪次方。如果是,返回 true ;否則,返回 false 。
如果存在一個整數 x 使得 n == 2x ,則認為 n 是 2 的冪次方。
class Solution {
public:
bool isPowerOfTwo(int n) {
if(n<=0) return false;
if(n==1) return true;
int p=1;
for(int i=1;i<=30;i++){
p *= 2;
if(p==n) return true;
}
return false;
}
};
3、3的冪
給定一個整數,寫一個函式來判斷它是否是 3 的冪次方。如果是,返回 true ;否則,返回 false 。
整數 n 是 3 的冪次方需滿足:存在整數 x 使得 n == 3x
class Solution {
public:
bool isPowerOfThree(int n) {
if(n<=0) return false;
if(n==1) return true;
int p=1;
for(int i=1;i<=19;i++){ //極限確定範圍
p *= 3;
if(p==n) return true;
}
return false;
}
};
4、4的冪
給定一個整數,寫一個函式來判斷它是否是 4 的冪次方。如果是,返回 true ;否則,返回 false 。
整數 n 是 4 的冪次方需滿足:存在整數 x 使得 n == 4x
class Solution {
public:
bool isPowerOfFour(int n) {
if(n<=0) return false;
if(n==1) return true;
int p=1;
for(int i=1;i<=15;i++){
p *= 4;
if(p==n) return true;
}
return false;
}
};
5、n 的第 k 個因子
給你兩個正整數 n 和 k 。
如果正整數 i 滿足 n % i == 0 ,那麼我們就說正整數 i 是整數 n 的因子。
考慮整數 n 的所有因子,將它們 升序排列 。請你返回第 k 個因子。如果 n 的因子數少於 k ,請你返回 -1 。
class Solution {
public:
int kthFactor(int n, int k) {
int cnt=0;
for(int i=1;i<=n;i++){
if(n%i==0) cnt++;
if(cnt==k) return i;
}
return -1;
}
};
//這個題目就是看樣例,不需要考慮重複的因子,需要從小到大判斷出所有的因子,從而避免排序
6、有效的完全平方數
給定一個 正整數 num ,編寫一個函式,如果 num 是一個完全平方數,則返回 true ,否則返回 false 。
進階:不要 使用任何內建的庫函式,如 sqrt 。
class Solution {
public:
bool isPerfectSquare(int num) {
for(int i=1;i<=46340;i++){ //注意這個46430的平方是最靠近2147483647的完全平方數
if(i*i==num) return true;
}
return false;
}
};