1. 程式人生 > >演算法題: 求一個整數陣列中,通過元素加減運算得到指定結果的所有運算過程. 例如【5,4,6,7,1】= 9 ?

演算法題: 求一個整數陣列中,通過元素加減運算得到指定結果的所有運算過程. 例如【5,4,6,7,1】= 9 ?

題目: 給定一個整數陣列int[] a (a.length > 1),和一個整數值 m,試輸出所有運算結果等於m的運算過程。可使用的運算方式只有加法和減法。陣列元素最多參與一次運算。例如,給定陣列【5,4,6,7,1】和整數9,輸出運算結果為9的運算過程如下:

+5+4=9
+5+4+6-7+1=9
+5+4-6+7-1=9
+5-4+7+1=9
+4+6-1=9
-4+6+7=9
-5+6+7+1=9

這個題目,我們可以使用回溯演算法得到所有的解。回溯法在問題的解空間樹中,按深度優先策略,從根節點出發搜尋解空間樹。演算法搜尋至解空間樹中的任一節點時,先判斷該節點是否包含問題的解。如果不包含,則跳過對已該結點為根的子數的搜尋,逐層向其祖先結點回溯。否則,進入該子樹,繼續按深度優先策略搜尋。回溯法求問題所有解時,要回溯到根,且根結點的所有子樹都已被搜尋遍才結束。回溯法求問題的一個解時,只要搜尋到問題的一個解就可結束。

回溯法通常包含3個步驟

  • 針對所給問題,定義問題的解空間
  • 確定易於搜尋的解空間結構。常見的結構一般為n叉樹結構,而且一般都是滿n叉樹。
  • 以深度優先方式搜尋解空間,並在搜尋過程中使用剪枝函式避免無效搜尋。深度優先策略可以選擇先序遍歷,中序遍歷,和後序遍歷。

對於給定的這個題目,我們首先要確定問題的解空間。由於如下的條件限定

  • 運算過程只能使用加法和減法
  • 陣列元素最多參與一次運算

我們可以把陣列元素的操作轉換為 (x1 * +1 ) + (x2 * -1) + (x3 * 0) ....... = ? ,以題目為例, 容易看出題目需要的解向量為 { (1,1,1,-1,1), (-1,0,1,1,1)..... } ,然後我們可以確定出解空間結構為一個3叉樹

,而且是一個滿三叉樹。三叉樹深度是給定陣列的長度加一,如題中陣列長度為5,那麼解空間結構的三叉樹的深度為6。由於篇幅限制,這裡只畫了最左部分節點的結構。


最後,剩下的步驟就是遍歷這顆三叉樹,檢查每個節點的結果是否符合要求。我們以根節點,左子樹,中子樹,和右子樹的順序進行深度優先遍歷。那麼以最左邊樹為例,其遍歷的結果如上圖所示,其中只有遍歷到第三層時的加法運算組合滿足要求 (5+4 = 9),那麼我們可以得到一個解向量,即 { (1,1,0,0,0) }。另外,符合要求的解,很有可能在葉子結點獲得。例如(5+4+6-7+1=9),對應的解向量為{ (1,1,1,-1,1 ) }。

程式碼如下

解空間

資料結構的節點類

  1. package com.csdn.blog.TechNerd.TraceBack;  
  2. /* 
  3.  * 構造樹節點,包含左子節點,中子節點,和右子節點的引用。以及該節點深度及資料資訊。 
  4.  */
  5. publicclass Node {  
  6.     private Node _lnode;  
  7.     private Node _rnode;  
  8.     private Node _mnode;  
  9.     privateint _data;  
  10.     privateint _depth;  
  11.     public Node(int data,int depth){  
  12.         this._data = data;  
  13.         this._depth = depth;  
  14.     }  
  15.     publicvoid setLNode(Node lnode){  
  16.         this._lnode = lnode;  
  17.     }  
  18.     publicvoid setMNode(Node mnode){  
  19.         this._mnode = mnode;  
  20.     }  
  21.     publicvoid setRNode(Node rnode){  
  22.         this._rnode = rnode;  
  23.     }  
  24.     publicint getData(){  
  25.         returnthis._data;  
  26.     }  
  27.     publicint getDepth(){  
  28.         returnthis._depth;  
  29.     }  
  30.     public Node getLNode(){  
  31.         returnthis._lnode;  
  32.     }  
  33.     public Node getMNode(){  
  34.         returnthis._mnode;  
  35.     }  
  36.     public Node getRNode(){  
  37.         returnthis._rnode;  
  38.     }  
  39. }  

如下類為解空間資料結構,包含回溯演算法的應用。
  1. package com.csdn.blog.TechNerd.TraceBack;  
  2. publicclass TraceBackTree {  
  3.     private Node _root;  
  4.     privateint _depth;  
  5.     privateint[] _a;    
  6.     privateint _m;     
  7.     public TraceBackTree(Node root,int depth,int[] a,int m){  
  8.         this._root = root;  
  9.         this._depth = depth;  
  10.         buildBTree();  
  11.         this._a = a;  
  12.         this._m = m;  
  13.     }  
  14.    /* 
  15.     * 構建解空間資料結構,題目所需要的是一個滿三叉樹。 
  16.     */
  17.     privatevoid buildBTree(){  
  18.         this._root.setLNode(createNode(1,2));  
  19.         this._root.setMNode(createNode(0,2));  
  20.         this._root.setRNode(createNode(-1,2));  
  21.     }  
  22.     private Node createNode(int data,int depth){  
  23.         if (depth <= this._depth){  
  24.             Node n = new Node(data,depth);  
  25.             n.setLNode(createNode(1,depth + 1));  
  26.             n.setMNode(createNode(0,depth + 1));  
  27.             n.setRNode(createNode(-1,depth +1));  
  28.             return n;  
  29.         }else{  
  30.             returnnull;  
  31.         }  
  32.     }  
  33.     /* 
  34.      * 按照根節點,左子節點,中子節點,右子節點的順序對數進行遍歷,列印所有節點。 
  35.      */
  36.     publicvoid preOrderTraverse(){  
  37.         preOrderTraverse(this._root);  
  38.     }  
  39.     privatevoid preOrderTraverse(Node n){  
  40.         if (n != null){  
  41.             printNode(n);  
  42.             preOrderTraverse(n.getLNode());  
  43.             preOrderTraverse(n.getMNode());  
  44.             preOrderTraverse(n.getRNode());  
  45.         }  
  46.     }  
  47.     privatevoid printNode(Node n){  
  48.         System.out.print(n.getData() + " ");  
  49.     }  
  50.     /* 
  51.      *回溯法求所有解。  
  52.      */
  53.     publicvoid backTrace(int[] a,int m){  
  54.         int[] x = newint[this._depth - 1]; //定義儲存解向量的陣列。該陣列長度與題目給定的陣列長度相等。
  55.         backTrace(this._root,x);  
  56.     }  
  57.     privatevoid backTrace(Node n,int[] x){  
  58.             if (n.getDepth() > 1) x[n.getDepth() - 2] = n.getData(); //將節點值付給解向量陣列。
  59.             if (constraints(x,n.getDepth() - 2)){   
  60.                 printSolution(x,n.getDepth() - 2);  
  61.             }  
  62.             if (n.getLNode() != null)   
  63.                 backTrace(n.getLNode(),x);  
  64.             if (n.getMNode() != null)   
  65.                 backTrace(n.getMNode(),x);  
  66.             if (n.getRNode() != null)   
  67.                 backTrace(n.getRNode(),x);  
  68.     }  
  69. /* 
  70.  * 檢查目前解向量是否滿足題目要求,就和等於指定值。 
  71.  */
  72. privateboolean constraints(int[] x,int boundary) {  
  73.         int sum = 0;  
  74.         for (int i=0;i<= boundary;i++){  
  75.             sum += _a[i] * x[i];   
  76.         }  
  77.         return (sum == _m && x[boundary] != 0);  
  78.     }  
  79.     privatevoid printSolution(int[] x,int boundary) {  
  80.         for (int i =0;i<= boundary;i++){  
  81.             if (x[i] == 1){  
  82.                 System.out.print("+"+ _a[i]);  
  83.             }elseif (x[i] == 0){  
  84.             }

    相關推薦

    演算法 一個整數陣列通過元素運算得到指定結果所有運算過程. 例如5,4,6,7,1= 9 ?

    題目: 給定一個整數陣列int[] a (a.length > 1),和一個整數值 m,試輸出所有運算結果等於m的運算過程。可使用的運算方式只有加法和減法。陣列元素最多參與一次運算。例如,給定陣列【5,4,6,7,1】和整數9,輸出運算結果為9的運算過程如下: +

    軟體工程課後作業2返回一個整數陣列最大子陣列的和

    #include <stdlib.h>#include <stdio.h>int GetMaxChildArraySum(int * pInput, int nLen, int * pOut){    if (!pInput || !pOut) 

    一個整數陣列有兩個元素只出現一次其他所有元素均出現兩次。 找出只出現一次的那兩個元素。(java實現)

    一個整數陣列中,有兩個元素只出現一次,其他所有元素均出現兩次。 找出只出現一次的那兩個元素。 思路大概是這樣的:因為除了這兩個只出現一次的數字外,其餘都是成對出現的,有一種運算子,異或運算,兩個相同的數字異或之後為0,所以將陣列中所有的數字依次異或,結果就是這個兩個支出現一

    Java演算法總結輸入一個整數整數的二進位制表示有多少個1

        求一個整數的二進位制中1的個數。      題目:輸入一個整數,求該整數的二進位制表達中有多少個1。例如輸入10,由於其二進位制表示為1010,有兩個1,因此輸出2。      分析:這是一道很基本的考查位運算的面試題。包括微軟在內的很多公司都曾採用過這道題。 

    演算法給定一個整數陣列一個目標值找出陣列中和為目標值的兩個數、判斷一個整數是否是迴文數

    <!-- 給定一個整數陣列和一個目標值,找出陣列中和為目標值的兩個數。 你可以假設每個輸入只對應一種答案,且同樣的元素不能被重複利用。 示例: 給定 nums = [2, 7, 11, 15], target = 9 因為 nums[0] + nums[1] = 2 + 7 = 9

    演算法N!末尾0的個數和二進位制數1的個數

    1、給定一個整數,那麼N的階乘N!末尾有多少個0呢? 解題思路:N!=K*10^M,M的值即為N!末尾0的個數。又10^M=(2^M)*(5^M),因為一個數進行質因數分解後,2出現的概率比5大得多。所以只有計算出1到N包含多少個5的因子 public class demo2 {

    演算法004 -- [給定一個整數陣列nums返回相加為target的兩個數字的索引值] by java

    題目 給定一個整數的陣列nums,返回相加為target的兩個數字的索引值。 假設每次輸入都只有一個答案,並且不會使用同一個元素兩次。 舉例: Given nums = [2, 7, 11, 15], target = 9, Because nums[0] + nums

    前端演算法給定一個整數陣列一個目標值找出陣列中和為目標值的兩個數、判斷一個整數是否是迴文數

    <!-- 給定一個整數陣列和一個目標值,找出陣列中和為目標值的兩個數。 你可以假設每個輸入只對應一種答案,且同樣的元素不能被重複利用。 示例: 給定 nums = [2, 7, 11, 15], target = 9 因為 nums[0] + nums[

    演算法1給定一個整數陣列一個目標值找出陣列中和為目標值的兩個數的index值。

    三種解決方法: 1、暴力法:遍歷每個num,查詢目標元素target-num class Solution: def twoSum(self, nums, target): """ :type nums: List[

    面試題一個整數陣列中和最大的連續子陣列例如[1, 2, -4, 4, 10, -3, 4, -5, 1]的最大連續子陣列是[4, 10, -3, 4](需寫明思路並程式設計實現)

    php實現: function get_max_value($arr) { $max_sum=0;//最大的值 $max_start=0;//和最大子陣列開始下標 $max_end=

    演算法給定一個整數陣列一個目標值找出陣列中和為目標值的兩個數

    給定一個整數陣列和一個目標值,找出陣列中和為目標值的兩個數。 你可以假設每個輸入只對應一種答案,且同樣的元素不能被重複利用。 示例: 給定 nums = [2, 7, 11, 15], tar

    c語言經典演算法——查詢一個整數陣列第二大數

    題目: 實現一個函式,查詢一個整數陣列中第二大數。 演算法思想: 設定兩個變數max1和max2,用來儲存最大數和第二大數,然後將陣列剩餘的數依次與這兩個數比較,如果這個數a比max1大,則先將max1賦給max2,使原先最大的數成為第二大的數,再將這個數a賦給max1,如

    調整陣列使奇數全部都位於偶數前面。 題目 輸入一個整數陣列實現一個函式來調整該陣列數字的順序使得陣列所有的奇數位於陣列的前半部分所有偶數位於陣列的後半部分。

    題目: 輸入一個整數陣列,實現一個函式,來調整該陣列中數字的順序使得陣列中所有的奇數位於陣列的前半部分,所有偶數位於陣列的後半部分。 #include <stdio.h> #includ

    返回一個整數陣列最大子陣列的和(迴圈)。

    要求:輸入一個整形陣列,數組裡有正數也有負數。陣列中連續的一個或多個整陣列成一個子陣列,每個子陣列都有一個和。如果陣列A[0]……A[j-1]首尾相鄰,允許A[i-1], …… A[n-1], A[0]……A[j-1]之和最大。同時返回最大子陣列的位置。求所有子陣列的和的最大值。 思路:在上次實驗的基礎上,

    題目:返回一個整數陣列最大子陣列的和。

    要求 1 要求程式必須能處理1000 個元素; 2 每個元素是int32 型別的; 3 輸入一個整形陣列,數組裡有正數也有負數。 4 陣列中連續的一個或多個整陣列成一個子陣列,每個子陣列都有一個和。 5 如果陣列A[0]……A[j-1]首尾相鄰

    返回一個整數陣列最大子陣列的和---環形陣列

    一、題目要求 題目:返回一個整數陣列中最大子陣列的和。 要求: 輸入一個整形陣列,數組裡有正數也有負數。 陣列中連續的一個或多個整陣列成一個子陣列,每個子陣列都有一個和。             

    結對開發之《返回一個整數陣列最大子陣列的和》

    一、題目要求 題目:返回一個整數陣列中最大子陣列的和。  要求: 輸入一個整形陣列,數組裡有正數也有負數。 陣列中連續的一個或多個整陣列成一個子陣列,每個子陣列都有一個和。           

    返回一個整數陣列最大子陣列的和 C語言

    1、題目:返回一個整數陣列中最大子陣列的和。 2、要求:  要求程式必須能處理1000 個元素;  每個元素是int32 型別的;  輸入一個整形陣列,數組裡有正數也有負數。  陣列中連續的一個或多個整陣列成一個子陣列,每個子陣列都有一個和。  求所有子陣列的和的最大值。要求時間複雜度為O(n)。 3、設計思

    LeetCode演算法JAVA實現整數反轉reverse integer

    題目來源:LeetCode Reverse digits of an integer. Example1: x = 123, return 321 Example2: x = -123, re

    劍指offer程式設計(JAVA實現)——第37數字在排序陣列出現的次數

    github https://github.com/JasonZhangCauc/JZOffer 劍指offer程式設計題(JAVA實現)——第37題:數字在排序陣列中出現的次數