Problem Statement for TheLuckySum (自己写的二叉树实现的4,7幸运数字算法。记录下来)

来源:互联网 发布:超次元矩阵要关服了吗 编辑:程序博客网 时间:2024/05/22 06:40

题目:
Problem Statement for TheLuckySum
Problem Statement
John thinks 4 and 7 are lucky digits, and all other digits are not lucky. A lucky number is a number that contains only lucky digits in decimal notation.
Some numbers can be represented as a sum of only lucky numbers. Given an int n, return a int[] whose elements sum to exactly n. Each element of the int[] must be a lucky number. If there are multiple solutions, only consider those that contain the minimum possible number of elements, and return the one among those that comes earliest lexicographically. A int[] a1 comes before a int[] a2 lexicographically if a1 contains a smaller number at the first position where they differ. If n cannot be represented as a sum of lucky numbers, return an empty int[] instead.
Definition
Class: TheLuckySum
Method: sum
Parameters: int
Returns: int[]
Method signature: int[] sum(int n)
(be sure your method is public)
  
Constraints
- n will be between 1 and 1,000,000,000, inclusive.
 
Examples
0)
11
Returns: {4, 7 }
It is simple: 11 = 4 + 7.
1)
12
Returns: {4, 4, 4 }
Now we need three summands to get 12.
2)
13
Returns: { }
And now we can not get 13 at all.
3)
100
Returns: {4, 4, 4, 44, 44 }
测试数据用例:
11 {4, 7}
12 {4, 4, 4}
13 {}
100 {4, 4, 4, 44, 44}
1000000000 {4, 4, 44444444, 477777774, 477777774}
48 {4, 44}
1 {}
57 {4, 4, 7, 7, 7, 7, 7, 7, 7}
25 {4, 7, 7, 7}
69 {4, 4, 7, 7, 47}
3603 {444, 444, 444, 747, 747, 777}
3456 {444, 744, 744, 747, 777}
3812 {47, 747, 747, 747, 747, 777}
3580 {4, 474, 774, 774, 777, 777}
3824 {44, 744, 744, 744, 774, 774}
957147 {4, 4, 444, 4444, 474474, 477777}
951000 {444, 444, 444, 444, 474447, 474777}
913356 {74, 4474, 44477, 44777, 44777, 774777}
971124 {4, 44, 4444, 44444, 444444, 477744}
998368 {44, 44, 444, 4444, 44444, 474474, 474474}
1 {}
2 {}
3 {}
4 {4}
5 {}
6 {}
7 {7}
8 {4, 4}
9 {}
10 {}
17 {}
18 {4, 7, 7}
19 {4, 4, 4, 7}
20 {4, 4, 4, 4, 4}
21 {7, 7, 7}
744399 {4, 4, 44, 474, 44774, 74774, 74774, 74774, 474777}

源代码:

/*
*:author:ChenGuoSong
*:date:2010-07-14
*/
#include <iostream>
#include <vector>
#include <stack>
using namespace std;
int isLuckNum(int i)
{
   if(0==i)
       return 0;
   while(i)
   {
        if(i%10==4||i%10==7)
            i = i/10;
        else
         return 0;
   }
   return 1;
}
//幸运数字二叉树节点
typedef struct BiTree
{
    int  num7;   //7的个数
    int  num4;   //4的个数
    int  radix;  //基数
    int  originalNum;//被分解的整数
    int  minCount; //可分解的个数最小限制
    int  minCP;  //和父亲节点minCount的差值
    BiTree *leftSon;
    BiTree *parent;
    BiTree *rightSon;
}BTree;
//临时变量,用于输出打印结果
stack<BTree*,vector<BTree*> > leafToRootStack ,leafToRootStackTmp1 ,leafToRootStackTmp2;
//分解整数,得到分解的4,7个数
int spilteNumber(int originalNum, int minCount, int &num7, int &num4, int &leftNum,int &radix,int isRightSon);
//打印结果
void print(stack<BTree*,vector<BTree*> > sp);
//取得整数的长度
int getIntLen(int i)
{
   int len = 1;
   while(i/=10)
      len ++;
   return len;
}
//取得当前长度的最小幸运数字
int getMinLuck(unsigned int len)
{
  int i = 4;
  while(--len)
    i = i*10+4;
  return i;
}
int powInt(unsigned int len)
{
 int i = 1;
 while(--len)
   i *= 10;
 return i;
}
//判断数是否可分解成幸运数字
int isSplited(int num)
{
  if (0>num)
    return 0;
  else if(11==num||15==num||17<num||0==num%4||0==num%7)
      return 1;
  else
    return 0;
}
//得到可分解的最高位数
int getSpliteNum(int originalNum ,int len,int minCount,int radix)
{
  int dif = originalNum-getMinLuck(len);
  if(0>=originalNum||(1==len&&4!=originalNum&&7!=originalNum&&8!=originalNum))
      return 0;
  if(1==len)
     return originalNum;
  else if(10!=len
          &&((0<minCount&&originalNum<radix)
             ||(0==minCount&&(isSplited(dif)||dif==3||10==dif||17==dif))))
    return  originalNum/powInt(len);
  else
    return originalNum/powInt(len-1);
}
//建立节点
int createNode(BTree *(&bitree),const BTree * const btParent)
{
  if(NULL==bitree)
  {
    int originalNum = btParent->originalNum,minCount = btParent->minCount,num7 = 0,num4 =0,leftNum=0,radix = btParent->radix,isRightSon=0;
    if(NULL!=btParent->leftSon)
       isRightSon=1;
    if(spilteNumber(originalNum,minCount,num7,num4,leftNum,radix,isRightSon))
    {
      bitree = new BTree;
      bitree->originalNum = leftNum;
      bitree->minCount = num7+num4;
      bitree->minCP = num7+num4-minCount;
      bitree->num7 = num7;
      bitree->num4 = num4;
      bitree->radix = radix;
      bitree->parent = (BTree*)btParent;
      bitree->leftSon = NULL;
      bitree->rightSon = NULL;
    }else
     return 0;
  }else
      return 1;
}
//先序建立二叉树
int preOrderCreateBTree(BTree *&bt,const BTree * const btParent)
{
  if(createNode(bt,btParent))
      if(preOrderCreateBTree(bt->leftSon,bt))
       if(preOrderCreateBTree(bt->rightSon,bt))
         return 1;
  return 1;
}
//遍历二叉幸运树,得到最幸运的一个分支
int findLeafToROOt(BTree * bt)
{
  int size = 0;
  if(NULL!=bt)
  {
    leafToRootStack.push(bt);
      if(NULL==bt->leftSon&&NULL==bt->rightSon)
      {
        if(bt->originalNum==0)
        {
         stack<BTree*,vector<BTree*> > leafToRootStackTmp = leafToRootStack;       
           if(leafToRootStackTmp1.empty()) 
           {
             leafToRootStackTmp1 = leafToRootStack;
             leafToRootStackTmp2 = leafToRootStack;  
           }
           else
           { 
           stack<BTree*,vector<BTree*> > leafToRootStackTmpbak = leafToRootStackTmp1 ;
             leafToRootStackTmp2 = leafToRootStack;
             while(!leafToRootStackTmp1.empty()&&!leafToRootStackTmp2.empty())
             {  
                if(leafToRootStackTmp1.top()->minCount<leafToRootStackTmp2.top()->minCount)
                  {
                      leafToRootStackTmp1 = leafToRootStackTmpbak ;
                      break;
                  }else if(leafToRootStackTmp1.top()->minCount==leafToRootStackTmp2.top()->minCount)
                  {
                     if(leafToRootStackTmp1.top()->minCP==leafToRootStackTmp2.top()->minCP)
                     {  
                        leafToRootStackTmp1.pop();
                        leafToRootStackTmp2.pop();
                        continue;
                     }else if(leafToRootStackTmp1.top()->minCP>leafToRootStackTmp2.top()->minCP)
                     {
                         leafToRootStackTmp1 = leafToRootStackTmpbak ;
                         break;
                     }else
                     {
                         leafToRootStackTmp1 = leafToRootStack;
                         break;
                     }
                  }else
                  {
                     leafToRootStackTmp1 = leafToRootStack;
                     break;  
                  }
             }
           }       
         }
      }
      if(findLeafToROOt(bt->leftSon))
      {
        if(NULL!=bt->leftSon)
          leafToRootStack.pop();
          if(findLeafToROOt(bt->rightSon))
          {
          if(NULL!=bt->rightSon)
            leafToRootStack.pop();         
              return 1;
          }
      }
  }
  else
    return 1;
}
int delBTree(BTree *&bt)
{
  if(NULL!=bt)
    if(delBTree(bt->leftSon))
        if(delBTree(bt->rightSon))  
        {
           delete [] bt;
         bt = NULL;
             return 1;
      }
  return 1;
}

int main(int argc,char *argv[])
{   
  while(1)
  {              
    BTree  *rootNode = new BTree;  
    cout << "input Number: " ;
    cin >>  rootNode->originalNum;
    //cout << i << "    ";
    if(0>rootNode->originalNum)
        break;
    if(isLuckNum(rootNode->originalNum))
    {
      cout << "the result:" << rootNode->originalNum <<" "<< endl;
      //cout << rootNode->originalNum <<" "<< endl;
      delete [] rootNode;
      rootNode = NULL;
        continue;
    }
    rootNode->minCount = 0;
    rootNode->num7 = 0;
    rootNode->num4 = 0;
    rootNode->radix = powInt(getIntLen(rootNode->originalNum));
    rootNode->minCP = 0;
    rootNode->parent =  NULL;
    rootNode->leftSon = NULL;
    rootNode->rightSon = NULL;
    preOrderCreateBTree(rootNode,rootNode->parent);
    findLeafToROOt(rootNode);
    cout << "the result:";
    print(leafToRootStackTmp1);
    delBTree(rootNode);
    while(!leafToRootStackTmp1.empty())
      leafToRootStackTmp1.pop();
    while(!leafToRootStackTmp2.empty())
      leafToRootStackTmp2.pop();
    while(!leafToRootStack.empty())
      leafToRootStack.pop();       
  }        
  cout << "good bye!" << endl;
  return 1;   
}      
//打印结果
void print(stack<BTree*,vector<BTree*> > sp)
{
  vector<int>  v,vTmp;
  int size = sp.size();
  for(int i=0;i<size-1;i++)
  {
     if(0==i)
     {
       for(int k=0;k<sp.top()->num4;k++)
       {  
         v.push_back(4);
       }
       for(int k=0;k<sp.top()->num7;k++)
       {  
         v.push_back(7);
       }          
     }else
     {
       for(int k=0;k<sp.top()->num7;k++)
       {  
         if(!v.empty())
         {
           vTmp.push_back(v.back()+7*sp.top()->radix);
           v.pop_back();
         }        
       }
       for(int k=0;k<sp.top()->num4;k++)
       {  
         if(!v.empty())
         {
           vTmp.push_back(v.back()+4*sp.top()->radix);
           v.pop_back();
         }     
       }
       while(!vTmp.empty())  
       {
         v.push_back(vTmp.back());
         vTmp.pop_back();
       }          
     }
     sp.pop();
  }
  if(v.empty())
  {
    cout << "此数无法分解" << endl;
    return ;
  }
  vector<int>::iterator it;
  for ( it=v.begin() ; it < v.end(); it++ )
    cout << *it << " ";
  cout << endl;
     
}
//数的分解
int spilteNumber(int originalNum, int minCount, int &num7, int &num4, int &leftNum,int &radix,int isRightSon)
{
  int len = getIntLen(originalNum);
  int spilteNum = getSpliteNum(originalNum,len,minCount,radix);
  if(0==spilteNum)
      return 0; 
  if(spilteNum>=10)
   radix = powInt(--len);
  else
   radix = powInt(len);
  int RightSonFlag = 1;
  while(spilteNum>=4)
  {  
   for(int k = spilteNum/7; k>=0; k--)
    for(int i = (spilteNum-k*7)/4;i*4+7*k<=spilteNum; i++)
    {
      leftNum = originalNum-7*k*radix-4*i*radix;
      int dif = leftNum-(i+k)*getMinLuck(len-1==0?1:len-1);
      if(i*4+7*k==spilteNum&&i+k>=minCount
         &&((1<len
              &&(isSplited(dif)||3==dif||((6==dif||13==dif)&&2<=k+i)||(9==dif&&3<=k+i)||10==dif||17==dif)
              &&isSplited(leftNum))
            ||(1==len&&spilteNum==originalNum)))
            
      {
        if(isRightSon)
        {
          isRightSon = 0;
          RightSonFlag = spilteNum;
          goto breakPoint;
        }else
        {
          num7 = k, num4 = i;
          return 1;
        }
      }
    }
   breakPoint:
     spilteNum--;
   if(1<RightSonFlag-spilteNum)
     break;
  }
  return 0;  //分解失败  
}

原创粉丝点击