主頁 > 軟體工程 > 如何在C 中以遞回方式找到不同的數字

如何在C 中以遞回方式找到不同的數字

2021-12-22 07:12:47 軟體工程

所以,假設陣列 A : 1,2,3,1,1,3 。不同的整數應該在陣列 B 中:1,2,3。然后,函式應該列印: [1,1][1,2][1,3][2,1][2,2][2,3][3,1][3,2][3, 3]。

我試圖解決不同的整數問題,但沒有遞回

#include <iostream>
#include <algorithm>
using namespace std;
    
void uniqueNumber(int A[], int n, int B[], int &dimB ){
    sort(A, A n);
    
    for( int i = 0; i < n; i   ){
        if( A[i] == A[i 1] ){
            continue;
        }
        else {
            B[dimB  ] = A[i];
        }
    }
}

但問題是我必須以遞回方式解決它,有什么想法嗎?

uj5u.com熱心網友回復:

我可以提供您的問題的解決方案,使用演算法深度優先搜索

#include <iostream>
#include <algorithm>
#include <set>
#include <vector>
void showContentSet(std::set<int>& input)
{
    for(auto iterator=input.begin(); iterator!=input.end();   iterator)
    {
        std::cout<<*iterator<<", ";
    }
    return;
}
void dfs(int current, int previous, std::vector<int>& first, std::set<int>& second, std::vector<int>& visited)
{
    if(visited[current]==1)
    {
        return;
    }
    visited[current]=1;
    for(int next=(current 1); next<first.size();   next)
    {
        if(next==previous)
        {
            continue;
        }
        if(first[next]==first[current])
        {
            continue;
        }
        else
        {
            second.insert(first[current]);
            second.insert(first[next]);
        }
        dfs(next, current, first, second, visited);
    }
    if(current==0)
    {
        for(auto& item : second)
        {
            for(auto& itemSet : second)
            {
                std::cout<<"["<<item<<", "<<itemSet<<"]"<<", ";
            }
        }
    }
    return;
}
void solve()
{
    const int maximumSize=20;
    std::vector<int> visited(maximumSize, 0);
    std::vector<int> inputVector={1, 2, 3, 1, 1, 3};
    std::set<int> inputSet;
    dfs(0, -1, inputVector, inputSet, visited);
    return;
}
int main()
{
    solve();
    return 0;
}

結果如下:

[1, 1], [1, 2], [1, 3], [2, 1], [2, 2], [2, 3], [3, 1], [3, 2], [3, 3],

uj5u.com熱心網友回復:

遞回只是另一種回圈方式。它通常是一種干凈的方法,盡管它通常不如實際forwhile回圈優化好,并且除了尾遞回演算法之外,它可以爆破堆疊記憶體,除非資料大小很小,或者演算法是對數的或更好的。這是一個線性演算法(遍歷陣列),所以我不喜歡真正解決方案的遞回,盡管它是一個很好的學習練習。

重要的是要考慮以下內容:資料的結構,什么是不變數(即,在遞回發生時您可以依靠什么來保持真實),以及何時應該停止(“基礎”案件)。

當您“通過”您的資料進行遞回時,您通常一次查看一個元素或一小塊資料,以逐步構建解決方案。

有時您必須在開始遞回之前直接處理一些特殊情況。這對于處理超出遞回所需的不變數的情況是必要的,例如當沒有足夠的資料來滿足資料的預期“形狀”時。

鑒于您的界面:

void uniqueNumber(int A[], int n, int B[], int &dimB );

我們已經知道一些事情。首先,它不是一個好的界面。:) 陣列不是函式的安全引數,并且非常容易出錯。其次,dimB 是一個“out”引數,除非有必要,否則不贊成(因為我們可以將大小作為函式回傳值回傳。)第三,我們不知道 B 的大小,但必須假設它在至少和 A 一樣大。(這是這個介面的另一個安全問題。)

但是假設函式簽名是固定的,這就是我們必須使用的。那么我們想要什么?

目標:找到每個唯一的數字,按排序順序寫入 B,然后更新 dimB 以告訴呼叫者有多少項寫入 B。

所以基本上我們想要這樣做:

  1. 對數字進行排序
  2. 使用索引迭代陣列 i
    • 如果當前值 ( A[i]) 與前一個值 ( A[i-1]) 不同,則將當前值附加到 B,并增加 dimB
    • 不要閱讀 A[-1]
  3. 增量 i
  4. 當索引 i == n 時,我們停止

上面的不變數是:

  • 對于任何索引 i,在它之前都有一個有效值
  • 索引i> 0 且 <= n
  • 每次遞回呼叫,i增加

主要步驟將是:

  1. 如果沒有作業要做(A 是空的),我們已經完成了。剛回來。

  2. 否則我們的不變數就滿足了:我們至少有一個元素。保證第一個元素不在 B 中,因此對 A 進行排序,然后立即將 A[0] 添加到 B,然后我們開始遞回。這也處理 A 的大小正好為 1 的情況。遞回將簡單地立即回傳。

通常,遞回演算法由兩個函式撰寫:第一個函式處理特殊情況并進行其他設定,然后呼叫執行遞回作業的第二個函式,知道所有特殊情況都已處理。

所以這里是考慮了上述之后的 uniqueNumbers 函式:

void uniqueNumber(int A[], int n, int B[], int &dimB ) {
    if (n > 0) {
        std::sort(A, A n);
        B[dimB  ] = A[0];
        detail::uniqueNumberRec(1, A, n, B, dimB);
    }
}

由于遞回輔助函式不是直接呼叫的,而是實作細節,我把它放在detail命名空間中,這是記錄用戶不應直接呼叫它的常見做法,它還有助于防止混亂全域命名空間。

那么遞回函式有什么作用呢?

它采用當前索引和初始函式采用的相同引數,并且是上述描述的非常直接的后果:

namespace detail {
void uniqueNumberRec(int curIdx, int A[], int n, int B[], int &dimB ) {

    // Base case: stop when we reach the end
    if (curIdx == n) {
        return;
    }

    // if current element differs from previous, include it in answer
    if (A[curIdx] != A[curIdx-1]) {
        B[dimB  ] = A[curIdx];
    }

    // recurse onto next element in sequence, so increment curIdx
    uniqueNumberRec(curIdx   1, A, n, B, dimB);
}
} // namespace detail

It's important to notice that the initial index passed into the recursive function (from the initail function) is 1, not 0, because we already added the first element to the output, and so are already past that.

As long as we know that curIdx 1 repeatedly called will eventually reach n, we know the recursion makes progress and will terminate. We already have verified n is positive in the first function.

A few things worth noting:

  • if n == 0 we do nothing
  • if n == 1, we add the only element of A into B, then recurse, but the recursion immediately stops since curIdx == 1 and n == 1
  • 如果 n > 1,我們添加(已排序)A 的第一個元素,然后遞回。所以 A[0] 已經在結果中,我們開始對 A[1] 進行遞回,知道 A[i-1](即 A[0])是一個有效的讀取元素。然后我們遞回,直到我們的索引在 n 處,這意味著我們完成了。

另外值得注意的是:在您的代碼中,您有一個錯誤:

    if( A[i] == A[i 1] ){

如果 i 是 A 中的最后一項,則 A[i 1] 讀取越界。這是不可接受的。這就是為什么我從以前的閱讀,確保有后以前的。

編譯器資源管理器示例:https : //godbolt.org/z/8z3cf5Tab

轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/389009.html

標籤:C 递归

上一篇:如何等待遞回回圈完成并顯示訊息?

下一篇:XSLT中有太多嵌套函式呼叫——尾遞回?

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • Git本地庫既關聯GitHub又關聯Gitee

    創建代碼倉庫 使用gitee舉例(github和gitee差不多) 1.在gitee右上角點擊+,選擇新建倉庫 ? 2.選擇填寫倉庫資訊,然后進行創建 ? 3.服務端已經準備好了,本地開始作準備 (1)Git 全域設定 git config --global user.name "成鈺" git c ......

    uj5u.com 2020-09-10 05:04:14 more
  • CODING DevOps 代碼質量實戰系列第二課,相約周三

    隨著 ToB(企業服務)的興起和 ToC(消費互聯網)產品進入成熟期,線上故障帶來的損失越來越大,代碼質量越來越重要,而「質量內建」正是 DevOps 核心理念之一。**《DevOps 代碼質量實戰(PHP 版)》**為 CODING DevOps 代碼質量實戰系列的第二課,同時也是本系列的 PHP ......

    uj5u.com 2020-09-10 05:07:43 more
  • 推薦Scrum書籍

    推薦Scrum書籍 直接上干貨,推薦書籍清單如下(推薦有順序的哦) Scrum指南 Scrum精髓 Scrum敏捷軟體開發 Scrum捷徑 硝煙中的Scrum和XP : 我們如何實施Scrum 敏捷軟體開發:Scrum實戰指南 Scrum要素 大規模Scrum:大規模敏捷組織的設計 用戶故事地圖 用 ......

    uj5u.com 2020-09-10 05:07:45 more
  • CODING DevOps 代碼質量實戰系列最后一課,周四發車

    隨著 ToB(企業服務)的興起和 ToC(消費互聯網)產品進入成熟期,線上故障帶來的損失越來越大,代碼質量越來越重要,而「質量內建」正是 DevOps 核心理念之一。 **《DevOps 代碼質量實戰(Java 版)》**為 CODING DevOps 代碼質量實戰系列的最后一課,同時也是本系列的 ......

    uj5u.com 2020-09-10 05:07:52 more
  • 敏捷軟體工程實踐書籍

    Scrum轉型想要做好,第一步先了解并真正落實Scrum,那么我推薦的Scrum書籍是要看懂并實踐的。第二步是團隊的工程實踐要做扎實。 下面推薦工程實踐書單: 重構:改善既有代碼的設計 決議極限編程 : 擁抱變化 代碼整潔代碼 程式員的職業素養 修改代碼的藝術 撰寫可讀代碼的藝術 測驗驅動開發 : ......

    uj5u.com 2020-09-10 05:07:55 more
  • Jenkins+svn+nginx實作windows環境自動部署vue前端專案

    前面文章介紹了Jenkins+svn+tomcat實作自動化部署,現在終于有空抽時間出來寫下Jenkins+svn+nginx實作自動部署vue前端專案。 jenkins的安裝和配置已經在前面文章進行介紹,下面介紹實作vue前端專案需要進行的哪些額外的步驟。 注意:在安裝jenkins和nginx的 ......

    uj5u.com 2020-09-10 05:08:49 more
  • CODING DevOps 微服務專案實戰系列第一課,明天等你

    CODING DevOps 微服務專案實戰系列第一課**《DevOps 微服務專案實戰:DevOps 初體驗》**將由 CODING DevOps 開發工程師 王寬老師 向大家介紹 DevOps 的基本理念,并探討為什么現代開發活動需要 DevOps,同時將以 eShopOnContainers 項 ......

    uj5u.com 2020-09-10 05:09:14 more
  • CODING DevOps 微服務專案實戰系列第二課來啦!

    近年來,工程專案的結構越來越復雜,需要接入合適的持續集成流水線形式,才能滿足更多變的需求,那么如何優雅地使用 CI 能力提升生產效率呢?CODING DevOps 微服務專案實戰系列第二課 《DevOps 微服務專案實戰:CI 進階用法》 將由 CODING DevOps 全堆疊工程師 何晨哲老師 向 ......

    uj5u.com 2020-09-10 05:09:33 more
  • CODING DevOps 微服務專案實戰系列最后一課,周四開講!

    隨著軟體工程越來越復雜化,如何在 Kubernetes 集群進行灰度發布成為了生產部署的”必修課“,而如何實作安全可控、自動化的灰度發布也成為了持續部署重點關注的問題。CODING DevOps 微服務專案實戰系列最后一課:**《DevOps 微服務專案實戰:基于 Nginx-ingress 的自動 ......

    uj5u.com 2020-09-10 05:10:00 more
  • CODING 儀表盤功能正式推出,實作作業資料可視化!

    CODING 儀表盤功能現已正式推出!該功能旨在用一張張統計卡片的形式,統計并展示使用 CODING 中所產生的資料。這意味著無需額外的設定,就可以收集歸納寶貴的作業資料并予之量化分析。這些海量的資料皆會以圖表或串列的方式躍然紙上,方便團隊成員隨時查看各專案的進度、狀態和指標,云端協作迎來真正意義上 ......

    uj5u.com 2020-09-10 05:11:01 more
最新发布
  • windows系統git使用ssh方式和gitee/github進行同步

    使用git來clone專案有兩種方式:HTTPS和SSH:
    HTTPS:不管是誰,拿到url隨便clone,但是在push的時候需要驗證用戶名和密碼;
    SSH:clone的專案你必須是擁有者或者管理員,而且需要在clone前添加SSH Key。SSH 在push的時候,是不需要輸入用戶名的,如果配置... ......

    uj5u.com 2023-04-19 08:41:12 more
  • windows系統git使用ssh方式和gitee/github進行同步

    使用git來clone專案有兩種方式:HTTPS和SSH:
    HTTPS:不管是誰,拿到url隨便clone,但是在push的時候需要驗證用戶名和密碼;
    SSH:clone的專案你必須是擁有者或者管理員,而且需要在clone前添加SSH Key。SSH 在push的時候,是不需要輸入用戶名的,如果配置... ......

    uj5u.com 2023-04-19 08:35:34 more
  • 2023年農牧行業6大CRM系統、5大場景盤點

    在物聯網、大資料、云計算、人工智能、自動化技術等現代資訊技術蓬勃發展與逐步成熟的背景下,數字化正成為農牧行業供給側結構性變革與高質量發展的核心驅動因素。因此,改造和提升傳統農牧業、開拓創新現代智慧農牧業,加快推進農牧業的現代化、資訊化、數字化建設已成為農牧業發展的重要方向。 當下,企業數字化轉型已經 ......

    uj5u.com 2023-04-18 08:05:44 more
  • 2023年農牧行業6大CRM系統、5大場景盤點

    在物聯網、大資料、云計算、人工智能、自動化技術等現代資訊技術蓬勃發展與逐步成熟的背景下,數字化正成為農牧行業供給側結構性變革與高質量發展的核心驅動因素。因此,改造和提升傳統農牧業、開拓創新現代智慧農牧業,加快推進農牧業的現代化、資訊化、數字化建設已成為農牧業發展的重要方向。 當下,企業數字化轉型已經 ......

    uj5u.com 2023-04-18 08:00:18 more
  • 計算機組成原理—存盤器

    計算機組成原理—硬體結構 二、存盤器 1.概述 存盤器是計算機系統中的記憶設備,用來存放程式和資料 1.1存盤器的層次結構 快取-主存層次主要解決CPU和主存速度不匹配的問題,速度接近快取 主存-輔存層次主要解決存盤系統的容量問題,容量接近與價位接近于主存 2.主存盤器 2.1概述 主存與CPU的聯 ......

    uj5u.com 2023-04-17 08:20:31 more
  • 談一談我對協同開發的一些認識

    如今各互聯網公司普通都使用敏捷開發,采用小步快跑的形式來進行專案開發。如果是小專案或者小需求,那一個開發可能就搞定了。但對于電商等復雜的系統,其功能多,結構復雜,一個人肯定是搞不定的,所以都是很多人來共同開發維護。以我曾經待過的商城團隊為例,光是后端開發就有七十多人。 為了更好地開發這類大型系統,往 ......

    uj5u.com 2023-04-17 08:18:55 more
  • 專案管理PRINCE2核心知識點整理

    PRINCE2,即 PRoject IN Controlled Environment(受控環境中的專案)是一種結構化的專案管理方法論,由英國政府內閣商務部(OGC)推出,是英國專案管理標準。
    PRINCE2 作為一種開放的方法論,是一套結構化的專案管理流程,描述了如何以一種邏輯性的、有組織的方法,... ......

    uj5u.com 2023-04-17 08:18:51 more
  • 談一談我對協同開發的一些認識

    如今各互聯網公司普通都使用敏捷開發,采用小步快跑的形式來進行專案開發。如果是小專案或者小需求,那一個開發可能就搞定了。但對于電商等復雜的系統,其功能多,結構復雜,一個人肯定是搞不定的,所以都是很多人來共同開發維護。以我曾經待過的商城團隊為例,光是后端開發就有七十多人。 為了更好地開發這類大型系統,往 ......

    uj5u.com 2023-04-17 08:18:00 more
  • 專案管理PRINCE2核心知識點整理

    PRINCE2,即 PRoject IN Controlled Environment(受控環境中的專案)是一種結構化的專案管理方法論,由英國政府內閣商務部(OGC)推出,是英國專案管理標準。
    PRINCE2 作為一種開放的方法論,是一套結構化的專案管理流程,描述了如何以一種邏輯性的、有組織的方法,... ......

    uj5u.com 2023-04-17 08:17:55 more
  • 計算機組成原理—存盤器

    計算機組成原理—硬體結構 二、存盤器 1.概述 存盤器是計算機系統中的記憶設備,用來存放程式和資料 1.1存盤器的層次結構 快取-主存層次主要解決CPU和主存速度不匹配的問題,速度接近快取 主存-輔存層次主要解決存盤系統的容量問題,容量接近與價位接近于主存 2.主存盤器 2.1概述 主存與CPU的聯 ......

    uj5u.com 2023-04-17 08:12:06 more