查看完整版本: 檢查數值是否有重複
頁: [1]

abcd345107 發表於 2016-11-9 04:48 PM

檢查數值是否有重複

本帖最後由 abcd345107 於 2016-11-9 04:54 PM 編輯

我又來請教惹,以下是題目 還有我的問題



問題描述 :給予一個由1到N的所有整數構成的數列,不依大小排列。 寫一函數檢查此數列是否每個數值只出現一次。
輸入說明 :輸入分為兩行,第一行是一個介於1與128間的正整數,代表第二行中數列中的數字個數。第二行是由空白鍵分隔開的數字序列,不超過128個數。每一個數值介於1到序列數字個數的整數。輸出說明 :若是每個數字剛好只出現一次則輸出1,輸出0表示其中有重複的數字。
範例 :

Sample Input:
Sample Output:

8
1 4 6 2 3 5 8 7
1




此題 我有個構想 程式碼如下:

#include<iostream>  
using namespace std;
int main()
{

        int buf;

        int n;
        cin >> n;
        int b = 0;

while (true)
{

if (cin >> buf)

b++;
else {                            <<這裡是昨天某大大教導,我拿來應用這題><
break;
}

}

int z = 0;

for (int i = 0; i > b; i++)
{
if (buf == n)  這裡的 這裡打不出來 X( 我在程式碼是有加的{
z++;
}
}

if (z == 1)
{
        cout << "1" << endl;
}
else
{
cout << "0" << endl;
}
        return 0;
}



但是我最終發現 輸出沒達到預期 ,經過逐步偵錯 我發現 我的z 一直是零 ,請問我觀念哪裡錯誤???



...<div class='locked'><em>瀏覽完整內容,請先 <a href='member.php?mod=register'>註冊</a> 或 <a href='javascript:;' onclick="lsSubmit()">登入會員</a></em></div><div></div>

baepi 發表於 2016-11-9 05:46 PM

首先~版規好像有說程式碼要用 代碼 包起來...就是長得像 <> 的圖示...找一下應該看的到
第二....看來我說的讓你誤會太大了....大大把我昨天說的東西忘光光吧...咱們走正規路線
首先....往後cin接收的容器請用字串...直到您完全懂資料型態之前....
然後在C++裡面~字串可以...如下char test; //這是由10個字元所組成的字串...不懂沒關係...總之記得這是普遍在C++裡面說的字串...也即是字元陣列所組成的

string test_2; //這也是字串...他沒所謂的固定長度....只有最大長度~印象中沒設定好像可以4294967295...吧因為根據您昨天的留言~得知課堂有教您使用下面那種~那就先用下面那種吧~對新手比較容易懂...也比較不會因為寫錯讓程式當掉^^

另外再補充一個大大現在應該還沒學到的觀念...昨天提過的~字串怎麼轉成數字呢?最簡單的方法是用atoi...範例如下        char test = "123";
        int n = atoi( test ) ;範例出來結果會是 n = 123....那假如test裡面放的不是正規數字呢?假如放ABC會怎麼樣...那樣就會轉換失敗....n = 0
或許您又會問~不對阿~可是這字串用的是上面提到的字元陣列的字串...不是叫我用的string阿...
那是因為~string也有可以把自己內容轉成字元陣列的輸出函式囉...範例如下string test = "456";
        int n = atoi( test.c_str() ) ;吹了半天...終於要進入題目...直接給程式碼 + 註解說明....建議看完後~覺得理解後~蓋起來重新自己寫寫看#include <iostream>
using namespace std;
#include <string>
int num;
void main()
{
        int sum;
        string buf ;

        cout<<"請輸入你要輸入多少個值 : ";
        cin>>sum;

        cout<<"請輸入那串落落長的數字 : ";

        for( int i = 0 ; i < sum ; i++ )        // 額外補充...很重要...這邊能這樣寫是因為空格對cin來說跟按下Enter可以理解為一樣動作
        {
                cin>>buf;
                cout<<"內容是 : "<<buf<<endl;
                num[ i ] = atoi( buf.c_str() );
                cout<<"轉換出來的數字是 : "<<num[ i ]<<endl;
        }

        //至於後面的檢查....自己動手~快樂無窮
}...<div class='locked'><em>瀏覽完整內容,請先 <a href='member.php?mod=register'>註冊</a> 或 <a href='javascript:;' onclick="lsSubmit()">登入會員</a></em></div>

abcd345107 發表於 2016-11-9 08:03 PM

baepi 發表於 2016-11-9 05:46 PM static/image/common/back.gif
首先~版規好像有說程式碼要用 代碼 包起來...就是長得像  的圖示...找一下應該看的到
第二....看來我說的讓 ...

感謝大大 我會好好研究~ 其實我又有新的問題但一直問 會變成太依賴大大X) 那就明天再問吧(也沒差多久X) ) ,感謝大大不厭其煩對我這新手的包容與講解...<div class='locked'><em>瀏覽完整內容,請先 <a href='member.php?mod=register'>註冊</a> 或 <a href='javascript:;' onclick="lsSubmit()">登入會員</a></em></div>

abcd345107 發表於 2016-11-10 07:48 PM

abcd345107 發表於 2016-11-9 08:03 PM static/image/common/back.gif
感謝大大 我會好好研究~ 其實我又有新的問題但一直問 會變成太依賴大大X) 那就明天再問吧(也沒差多久X) ) ...

我有個問題 那就 我們老師說過 string 也有包含數字 那為何我們又特別轉變成真正數字?

baepi 發表於 2016-11-10 08:55 PM

本帖最後由 baepi 於 2016-11-10 09:24 PM 編輯

abcd345107 發表於 2016-11-10 07:48 PM static/image/common/back.gif
我有個問題 那就 我們老師說過 string 也有包含數字 那為何我們又特別轉變成真正數字? ...
老實說~看不懂大大想表明甚麼...相信點評的超級高手S大大也不是很確定對方想表達的吧...
以下是我的猜測~大大是想說~怎麼不把程式碼改成如下~
真糟糕~手賤按太快...沒辦法在代碼底下繼續打了....只好補充在這裡~那是因為~我只是兩種方法都教
cin>...<div class='locked'><em>瀏覽完整內容,請先 <a href='member.php?mod=register'>註冊</a> 或 <a href='javascript:;' onclick="lsSubmit()">登入會員</a></em></div><br><br><br><br><br><div></div>

abcd345107 發表於 2016-11-11 02:29 AM

本帖最後由 abcd345107 於 2016-11-11 02:42 AM 編輯

我最後解出來了 感謝大大提點,然後我的意思是這樣的 不是用以下程式碼也可以?
#include <iostream>
using namespace std;
#include <string>

void main()
{
        int sum;
        string buf;

        cout << "請輸入你要輸入多少個值 : ";
        cin >> sum;

        cout << "請輸入那串落落長的數字 : ";

        cin >> buf;這裡直接輸入完 不用空白
        for (int i = 0; i < sum; i++)      
        {
               
                cout << "轉換出來的數字是 : " << buf [ i ] << endl;
        }

        
}


也就是 我都用string 我不可以直接, 打個字串 比方說 123456,然後再從字串裡面檢查??


然後以下是我解出來的方法:
粗暴解法的感覺=w

[*]#include<iostream>      
[*]using namespace std;  
[*]  
[*]  
[*]  
[*]int main()  
[*]{  
[*]    int  N = { 0 };  
[*]    int bf = { 0 };  
[*]    int s;  
[*]  
[*]  
[*]    while (cin >> s)  
[*]    {  
[*]  
[*]  
[*]        if (1 < s&&s < 128)  
[*]        {  
[*]            N = s;  
[*]        }  
[*]        int b = 0;  
[*]        for (int i = 0;i <128;i++)  
[*]  
[*]        {  
[*]  
[*]  
[*]            int a = 0;  
[*]            if (cin >> a)  
[*]            {  
[*]  
[*]  
[*]                b++;  
[*]                bf++;  
[*]            }  
[*]  
[*]  
[*]        }  
[*]  
[*]  
[*]  
[*]  
[*]        int z = 0;  
[*]  
[*]        for (int j = 0;j <b;j++)  
[*]        {  
[*]            if (bf >1)  
[*]  
[*]                z++;  
[*]  
[*]        }  
[*]        if (z == 0)  
[*]  
[*]        {  
[*]            cout << "1" << endl;;  
[*]        }  
[*]  
[*]        else  
[*]        {  
[*]            cout << "0" << endl;  
[*]  
[*]        }  
[*]    }  
[*]  
[*]    return 0;  
[*]}  



...<div class='locked'><em>瀏覽完整內容,請先 <a href='member.php?mod=register'>註冊</a> 或 <a href='javascript:;' onclick="lsSubmit()">登入會員</a></em></div>

abcd345107 發表於 2016-11-11 02:41 AM

baepi 發表於 2016-11-10 08:55 PM static/image/common/back.gif
老實說~看不懂大大想表明甚麼...相信點評的超級高手S大大也不是很確定對方想表達的吧...
以下是我的猜測~ ...

多學點 當然更好 感謝大大們 願意賜教囉~  不過 可能我的問題太過新手級,而在下常常因為一些小地方鑽牛角尖
所以造成大大們無法理解 也請多包涵>...<div class='locked'><em>瀏覽完整內容,請先 <a href='member.php?mod=register'>註冊</a> 或 <a href='javascript:;' onclick="lsSubmit()">登入會員</a></em></div>

inunu 發表於 2016-11-11 03:21 AM

string 本身也可以被用來進行比較, 也就是說
1. 切割字串
2. 字串轉數字
3. 數字比較

1. 切割字串
2. 字串比較
是一樣的功能

但, 用字串的話要再考慮輸入規則
題目要求:
"第二行是由空白鍵分隔開的數字序列,不超過128個數。
每一個數值介於1到序列數字個數的整數。"
所以輸入範圍只有 1 ~ 128, 而且受數列位置限制
例如 "1 2 3 5" 第四個數字的 5 就不合規定
也就是你還是得轉成數字來測試輸入是否合理
否則它故意來組錯誤的輸入你就 WA 了

總之做法有很多, 看哪種比較適合你的思考模式...<div class='locked'><em>瀏覽完整內容,請先 <a href='member.php?mod=register'>註冊</a> 或 <a href='javascript:;' onclick="lsSubmit()">登入會員</a></em></div>

baepi 發表於 2016-11-11 11:21 AM

看懂大大期望的程式邏輯...只是大大真的讓程式跑過嗎?感覺錯很大哪~
另外還是那句題外話~cin雖然可以用int去收...但還是盡量避免這麼做...更別說 while (cin >> s)  這樣的東西出現...畢竟要cin錯誤的代價就是....他將永遠的錯下去~
如果今天你要程式往下一個階段走的代價是要程式先出錯....在這作業看起來問題是不大~畢竟輸入完後就是秀出結果了...可是假如你今天這段程式只是大程式的一部分....那麼當下次要在重新使用你這部分的程式碼功能時....他仍然是壞掉的....
所以本帖剛開始我才會說~把我前一篇說的忘掉~咱們學正規的

另外回歸主線問題...放的仍是大大覺得比較直觀的直接用int收納cin導入的值...如下#include <iostream>
using namespace std;

void main()
{
        int num ={0};
        int sum = 0 ;

        int buf_int ;

        int ans = 0;

        cout << "請輸入你要輸入多少個值 : " ;
        cin >> sum ;

        if( sum <= 0 )
        {
                cout << "輸入的值也太小\n";
                system("pause") ;        //讓程式暫停讓你看看啥情況
                return ;        // 跳離主程式~意指離開程式

        }

    cout << "請輸入那串落落長的數字 : " ;

    for( int i = 0 ; i < sum ; i++ )
    {
            cin >> buf_int ;
            cout << "拿到的數字是 : " << buf_int << endl ;
                        if( (buf_int >= 0) && (buf_int < 128) )
                        {
                                num [ buf_int - 1 ] ++;
                        }
                        else
                        {
                                cout << "輸入太大啦\n" ;
                        }
    }

        cout << "\n---傳說的分隔線---\n以下顯示收到資料整理\n\n" ;

        for( int i = 0 ; i < 128 ; i++ )
        {
                if( num[ i ] > 0 )
                {
                        cout << (i + 1) << "共收到了" << num[ i ] << "次\n" ;
                        if( num[ i ] > 1 )
                        {
                                ans ++ ;
                        }
                }
        }

        if( ans > 0 )
        {
                cout<<"\n有重複~不信自己查\n" ;
        }
        else
        {
                cout<<"\n沒重複~不信拉倒\n" ;
        }

        system("pause") ;        //讓程式暫停讓你看看啥情況
}執行結果範例...正常輸入的情況下請輸入你要輸入多少個值 : 5
請輸入那串落落長的數字 : 1 6 2 4 3
拿到的數字是 : 1
拿到的數字是 : 6
拿到的數字是 : 2
拿到的數字是 : 4
拿到的數字是 : 3

---傳說的分隔線---
以下顯示收到資料整理

1共收到了1次
2共收到了1次
3共收到了1次
4共收到了1次
6共收到了1次

沒重複~不信拉倒
請按任意鍵繼續 . . .範例2...手殘按到非數字非空格的版本請輸入你要輸入多少個值 : 5
請輸入那串落落長的數字 : 2 3 1w 6 2
拿到的數字是 : 2
拿到的數字是 : 3
拿到的數字是 : 1
拿到的數字是 : 1
拿到的數字是 : 1

--傳說的分隔線---
以下顯示收到資料整理

共收到了3次
共收到了1次
共收到了1次

有重複~不信自己查
請按任意鍵繼續 . . .因此可以看出~如果今天只是作業...要學習怎麼做~這程式肯定沒甚麼問題...詳見範例1
但是程式寫好本來就不是給自己用的(?)....當大專案的程式是手殘按錯後就不能修復~那肯定是不允許的....所以~多學一個收到的資料先丟到字串再轉成你期望的資料型態是必要的喔~...<div class='locked'><em>瀏覽完整內容,請先 <a href='member.php?mod=register'>註冊</a> 或 <a href='javascript:;' onclick="lsSubmit()">登入會員</a></em></div>

kiwis 發表於 2016-11-14 09:48 PM

int CheckValue(int* array, int length)
{
        int ans(1);
        char record_book;
        memset(record_book, 0, 128*sizeof(char));

        for(int i(0); i<length; ++i)
        {
                int rec_index( (array-1) );
                if( !record_book[ rec_index ] )
                        ++record_book[ rec_index ];
                else
                {
                        ans = 0;
                        break;
                }
        }

        return ans;
}用一個 長度的陣列來記錄輸入的數字陣列中的數字出現次數,如果發現有大於 1 就是該數字重複,馬上 break & return。

上面的做法的缺點是如果輸入的陣列很短,會有很多記憶體浪費沒用到 : p...<div class='locked'><em>瀏覽完整內容,請先 <a href='member.php?mod=register'>註冊</a> 或 <a href='javascript:;' onclick="lsSubmit()">登入會員</a></em></div><br><br><br><br><br><div></div>

CoNsTaRwU 發表於 2016-11-20 08:25 PM

本帖最後由 CoNsTaRwU 於 2016-11-20 08:39 PM 編輯

你只需要一個 find (下面的 elem) 然後遞迴/迭代下去就可以了
noDup : → Bool
noDup [] = true
noDup (x::xs) = (not $ elem x xs) && (noDup xs)
1. 取一個正整數 List 並回傳 Bool
2. 如果為空 List 直接回傳 true
3. 先檢查首項(x)是否在後面(xs)重複出現,沒有的話對去除首項的 List 做一樣的檢查直到變為空 List
頁: [1]