九度OJ题目1359--1414解题练习(七)


题目1361:翻转单词顺序

题目描述:
JOBDU最近来了一个新员工Fish,每天早晨总是会拿着一本英文杂志,写些句子在本子上。同事Cat对Fish写的内容颇感兴趣,有一天他向Fish借来翻看,但却读不懂它的意思。例如,“student. a am I”。后来才意识到,这家伙原来把句子单词的顺序翻转了,正确的句子应该是“I am a student.”。Cat对一一的翻转这些单词顺序可不在行,你能帮助他么?
输入:
每个测试案例为一行,表示一句英文句子。
我们保证一个句子的单词数不会超过600,每个单词的长度也不会超过30。但是需要注意的是Fish是个不拘小节的人,有时候两个单词中间可能会有很多空格。为了方便起见,你可以认为一行的字符总数不会超过50000个,标点符号可以和普通字母一样处理。
输出:
对应每个测试案例,把翻转后的正确的句子单独输出一行。
样例输入:
student. a am I
I'm a Freshman and I like JOBDU!
样例输出:
I am a student.
JOBDU! like I and Freshman a I'm

#include "string"
#include "algorithm"
#include 
#include "stack"
#include   
 
using namespace std;
//先将所有字符倒置,然后对单个字符倒置
int main() 
{
    string str;
    while (getline(cin,str)) 
    {
        reverse(str.begin(),str.end());//将整个字符串倒置
        int nBegin = 0, nEnd = 0;
        char ch = ' ';
        int pos = 0;
        while (true)
        {
            //找出即将进行部分倒置的字符串的起始位置到该子字符串后的空格位置
            if (pos==0)//第一次起始位置在0处
                nBegin = pos;
            else//以后的位置在前一个空格下一个位置开始才是下一个字符的起始位置
                nBegin = pos+1;
            pos = str.find(ch,pos+1);//从空格的下一个位置找到新空格的位置
            if (pos == std::string::npos)//如果是末尾,直接倒置
            {
                reverse(str.begin() + nBegin, str.end());
                break;
            }
            nEnd = pos;
            //部分倒置
            reverse(str.begin() + nBegin, str.begin() + nEnd);//将整个子字符串倒置
             
        }
        cout << str << endl;
    }
    return 0;
}
/**************************************************************
    Problem: 1361
    User: EbowTang
    Language: C++
    Result: Accepted
    Time:150 ms
    Memory:1520 kb
****************************************************************/

题目1366:栈的压入、弹出序列

题目描述:

输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压栈序列对应的一个弹出序列,但4,3,5,1,2就不可能是该压栈序列的弹出序列。

输入:

每个测试案例包括3行:

第一行为1个整数n(1<=n<=100000),表示序列的长度。

第二行包含n个整数,表示栈的压入顺序。

第三行包含n个整数,表示栈的弹出顺序。

输出:

对应每个测试案例,如果第二个序列是第一个序列的弹出序列输出Yes,否则输出No。

样例输入:
51 2 3 4 54 5 3 2 151 2 3 4 54 3 5 1 2
样例输出:
YesNo

#include //小数点精确
#include 
#include "vector"
#include "string"
#include "algorithm"
#include 
 
using namespace std;
 
class Stack
{
public:
    Stack(int size)
    {
        elements = new int[size];
        top = -1;
    }
    ~Stack()
    {
        delete[] elements;
        elements = NULL;
    }
    bool push(int ndata);//压入元素到栈顶
    void popTop();//弹出栈顶元素
    int getTop();
    bool empty();
private:
    int *elements;
    int top;                     //始终指向栈顶,top=0,就表示有一个数据了  
};
 
//压入元素
bool Stack::push(int ndata)
{
    top++;
    elements[top] = ndata;//从栈顶压入元素 
    return true;
}
bool  Stack::empty()
{
    if (top == -1)
        return true;
    else
        return false;
}
 
int  Stack::getTop()
{
    if (top > -1)
        return elements[top];
}
 
//除去栈顶元素
void Stack::popTop()
{
    if (top > -1)
        top--;
}
 
int main()
{
    int n = 0;
    while (cin>>n)
    {
        //重新按照第一组数据入栈,每次入栈后都检查下是否跟出栈顺序内容相同,
        //如果相同,则立马出栈。否则暂时不作处理
        //然后,将栈顶的元素与相应的出栈顺序比较,如果相同则出栈,
        //最后如果这个栈内不存在元素,则证明第二个序列为出栈序列。
        Stack s1(1000);
        vector avec(n), bvec(n);
        for (int i = 0; i < n; i++)
            cin >> avec[i];
         
        for (int i = 0; i < n; i++)
            cin >> bvec[i];
 
        int i = 0, j = 0;
        while (i


题目1368:二叉树中和为某一值的路径

题目描述:

输入一颗二叉树和一个整数,打印出二叉树中结点值的和为输入整数的所有路径。路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一条路径。

输入:

每个测试案例包括n+1行:

第一行为2个整数n,k(1<=n<=10000),n表示结点的个数,k表示要求的路径和,结点编号从1到n。                                                                                                       

接下来有n行。这n行中每行为3个整数vi,leftnode,rightnode,vi表示第i个结点的值,leftnode表示第i个结点的左孩子结点编号,rightnode表示第i个结点的右孩子结点编号,若无结点值为-1。编号为1的结点为根结点。

输出:

对应每个测试案例,先输出“result:”占一行,接下来按字典顺序输出满足条件的所有路径,这些路径由结点编号组成,输出格式参照输出样例。

样例输入:
5 2210 2 35 4 512 -1 -14 -1 -17 -1 -11 51 -1 -1
样例输出:
result:A path is found: 1 2 5A path is found: 1 3result:

#include "queue"
#include "vector"
#include "string"
#include "algorithm"
#include 
#include "stack"
#include 
#include 
 
using namespace std;
 
// 节点定义  
class BSTNode
{
public:
    BSTNode()// 默认构造  
    {
        pRight = NULL;
        pLeft = NULL;
        value = 0;
        count = 0;
    }
    friend class LinkBST;// 允许链表类随意访问节点数据  
 
private:
    int value;
    BSTNode *pRight;
    BSTNode *pLeft;
    int count;
};
 
// 不带头结点的二叉树定义   
class LinkBST
{
public:
    LinkBST(int size)
    {
        m_pNode = new BSTNode[size + 1];
    }
    ~LinkBST()
    {
        delete[] m_pNode;
        m_pNode = NULL;
    }
    // 连接节点集(形成一棵树)  
    void LinkBSTNode(int nValue ,int lnode, int rnode, int pos);
 
    void FindTPathSum(BSTNode *pRoot, const int exNum, vector& path, int &curNum);
 
    void FindPath(BSTNode *&pRoot, int exceptionNum);
 
    // 节点集  
    BSTNode *m_pNode;
 
};
 
//用前序遍历的方式搜索路劲
void LinkBST::FindTPathSum(BSTNode *pRoot,const int exNum, vector& path, int &curNum)
{
    curNum += pRoot->value;
    path.push_back(pRoot->count);
 
    //如果pRoot是叶节点,并且路径上节点的值的和等于输入的值
    //打印这条路径
    bool isLeaf = (pRoot->pLeft == NULL) && (pRoot->pRight == NULL);
    if (isLeaf && curNum == exNum)
    {
        cout << "A path is found: ";
        vector::iterator iter = path.begin();
        for (; iter != path.end(); iter++)
            cout << *iter << " ";
        cout << endl;
    }
 
    //如果pRoot不是叶节点,则遍历其子节点
    if (pRoot->pLeft != NULL)
        FindTPathSum(pRoot->pLeft, exNum, path, curNum);
    if (pRoot->pRight != NULL)
        FindTPathSum(pRoot->pRight, exNum, path, curNum);
 
    //在返回到父节点之前,在路径上删除当前pRoot节点的count
    curNum -= pRoot->value;
    path.pop_back();
}
 
 
void LinkBST::FindPath(BSTNode *&pRoot, int exceptionNum)
{
    if (pRoot == NULL)
        return;
    vector vecpath;
    int currentNum = 0;
    FindTPathSum(pRoot, exceptionNum, vecpath, currentNum);
}
 
// 连接节点集(形成一棵树)  
void LinkBST::LinkBSTNode(int nValue, int lnode, int rnode, int pos)
{
    m_pNode[pos].value = nValue;
    m_pNode[pos].count = pos;
    if (lnode != -1)
        m_pNode[pos].pLeft = &m_pNode[lnode];
    if (rnode != -1)
        m_pNode[pos].pRight = &m_pNode[rnode];
}
 
int main()
{
    int n = 0, exSum = 0;
    while (cin >> n >> exSum)
    {
        BSTNode *pRoot = NULL;
        LinkBST bst(n);
        pRoot = &bst.m_pNode[1];//指向根节点  
        int value = 0, nleftnode = 0, nrightnode = 0;
        //插入节点,建立连接
        for (int i = 1; i <= n; i++)
        {
            cin >>value>> nleftnode >> nrightnode;
            if (nleftnode>n || nrightnode > n)
                exit(1);
            bst.LinkBSTNode(value,nleftnode, nrightnode, i);//第i个节点指向第nleftnode个节点和第nrightnode节点  
            int a = 0;
        }
        cout << "result:" << endl;
        bst.FindPath(pRoot,exSum);
    }
}
 
/**************************************************************
    Problem: 1368
    User: EbowTang
    Language: C++
    Result: Wrong Answer
****************************************************************/





题目1371:最小的K个数

题目描述:

输入n个整数,找出其中最小的K个数。例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,。

输入:

每个测试案例包括2行:

第一行为2个整数n,k(1<=n,k<=200000),表示数组的长度。

第二行包含n个整数,表示这n个数,数组中的数的范围是[0,1000 000 000]。

方法:

方法1:直接用排序法将整个数据排序,然后输出前k个数
方法2:随机选取数组中的三个数,取他们的中间值,然后运用快排的划界方法寻找这个数的“中间”位置,如果这个位置比k大则继续在前面寻找三个随机数的中间值找出其“中间位置”与k比较......直到找到k
方法3:申请k个容量的最大堆


输出:

对应每个测试案例,输出最小的k个数,并按从小到大顺序打印。

样例输入:
8 44 5 1 6 2 7 3 8
样例输出:
1 2 3 4

C++程序实现如下:

直接排序:

[html]  view plain copy print ?
  1. #include <iostream>    
  2. #include <vector>  
  3. #include <algorithm>  
  4. using namespace std;  
  5.    
  6. int main()  
  7. {  
  8.     int n, k;  
  9.     while (cin >> n >> k)  
  10.     {  
  11.         vector<int> vIn(n);//创建n个空元素  
  12.    
  13.         for (int i = 0; i < n; ++i)//获取n个元素  
  14.         {  
  15.             cin >> vIn[i];  
  16.         }  
  17.         sort(vIn.begin(), vIn.end());//将其排序  
  18.    
  19.         for (int i = 0; i < k - 1; i++)//输出前k个最小数  
  20.         {  
  21.             cout << vIn[i] << " ";  
  22.         }  
  23.         cout << vIn[k-1];  
  24.         //vIn.clear();  
  25.         cout << endl;  
  26.            
  27.     }  
  28.     return 0;  
  29. }  
  30. /**************************************************************  
  31.     Problem: 1371  
  32.     User: EbowTang  
  33.     Language: C++  
  34.     Result: Time Limit Exceed  
  35. ****************************************************************/  


方法2:快排划界

[html]  view plain copy print ?
  1. #include <iostream>    
  2. #include <vector>  
  3. #include <algorithm>  
  4. using namespace std;  
  5.   
  6.   
  7. int Partition(vector<int> &a, int high);  
  8. void swap(int *a, int *b);  
  9. int randomizedSelect(vector<int> &a, int left, int right, int k);  
  10.   
  11. int main()  
  12. {  
  13.       
  14.     int n, k;  
  15.     while (cin >> n >> k)  
  16.     {  
  17.         if (k > 200000)  
  18.         {  
  19.             break;  
  20.         }  
  21.         vector<int> vIn(n);//创建n个空元素    
  22.         for (int i = 0; i < n; i++)//获取n个元素    
  23.         {  
  24.             cin >> vIn[i];  
  25.             if (vIn[i]>1000000000)  
  26.             {  
  27.                 break;  
  28.             }  
  29.         }  
  30.   
  31.         randomizedSelect(vIn, 0, n-1, k);//反复划界到k的位置  
  32.   
  33.         vector<int> vIn1(k);//创建k个空元素  
  34.   
  35.         for (int i = 0; i < k; i++)   
  36.         {  
  37.             vIn1[i]=vIn[i];  
  38.         }  
  39.         sort(vIn1.begin(), vIn1.end());  
  40.   
  41.         for (int i = 0; i < k; i++)  
  42.         {  
  43.             cout<< vIn1[i]<<" ";  
  44.         }  
  45.         cout << endl;  
  46.         vIn.clear();    
  47.     }  
  48.     return 0;  
  49. }  
  50.   
  51.   
  52.   
  53. void swap(int *a, int *b)  
  54. {  
  55.     int temp;  
  56.     temp = *a;  
  57.     *a = *b;  
  58.     *b = temp;  
  59. }  
  60.   
  61. //快速排序的划界函数,寻找pivotkey在数组a中的“划界位置”,返回的是数组的下标位置  
  62. int Partition(vector<int> &a,int low, int high)  
  63. {  
  64.     int pivotkey = a[high];//选择主元,即基准元素    
  65.     int i = low -1;  
  66.     for (int j = low; j < high; j++)  
  67.     {  
  68.   
  69.         if (a[j] < pivotkey && i != j)  
  70.         {  
  71.             i++;  
  72.             swap(&a[i], &a[j]);  
  73.         }  
  74.     }  
  75.   
  76.     i++;  
  77.     swap(&a[i], &a[high]);  
  78.     return i;  
  79. }  
  80.   
  81. int randomizedSelect(vector<int> &a, int low, int high, int k)   
  82. {  
  83.     if (low < 0 || (high - low + 1) < k)  
  84.         return -1;//error  
  85.   
  86.     int midPos = Partition(a, low, high);  
  87.   
  88.     int m = midPos - low + 1;  
  89.   
  90.     if (k == m) //前面的k个数已经小于后面所有数  
  91.     {  
  92.         return midPos;  
  93.     }  
  94.     else if (k < m)  
  95.     {  
  96.         return randomizedSelect(a, low, midPos - 1, k);  
  97.     }  
  98.     else   
  99.     {  
  100.         return randomizedSelect(a, midPos + 1, high, k - m);  
  101.     }  

题目1384:二维数组中的查找

题目描述:

在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。

输入:

输入可能包含多个测试样例,对于每个测试案例,

输入的第一行为两个整数m和n(1<=m,n<=1000):代表将要输入的矩阵的行数和列数。

输入的第二行包括一个整数t(1<=t<=1000000):代表要查找的数字。

接下来的m行,每行有n个数,代表题目所给出的m行n列的矩阵(矩阵如题目描述所示,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。

输出:

对应每个测试案例,

输出”Yes”代表在二维数组中找到了数字t。

输出”No”代表在二维数组中没有找到数字t。

样例输入:
3 351 2 34 5 67 8 93 312 3 45 6 78 9 103 3122 3 45 6 78 9 10
样例输出:
YesNoNo

#include 
  
int m, n;
int t;
int a[1000][1000];
  
void getRes() {
    int row = 0, col = n - 1;
    while (col >=0 && row < m) {
        if (a[row][col] > t) {
            --col;
        } else if (a[row][col] < t) {
            ++row;
        } else {
            printf("Yes\n");
            return;
        }
    }
    printf("No\n");
}
  
int main() {
    while (scanf("%d %d", &m, &n) != EOF) {
        scanf("%d", &t);
        for (int i = 0; i < m; ++i) {
            for (int j = 0; j < n; ++j) {
                scanf("%d", &a[i][j]);
            }
        }
        getRes();
    }
    return 0;
}
  
/**************************************************************
    Problem: 1384
    User: EbowTang
    Language: C++
    Result: Accepted
    Time:680 ms
    Memory:4928 kb
****************************************************************/


题目1385:重建二叉树

题目描述:

输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并输出它的后序遍历序列。

输入:

输入可能包含多个测试样例,对于每个测试案例,

输入的第一行为一个整数n(1<=n<=1000):代表二叉树的节点个数。

输入的第二行包括n个整数(其中每个元素a的范围为(1<=a<=1000)):代表二叉树的前序遍历序列。

输入的第三行包括n个整数(其中每个元素a的范围为(1<=a<=1000)):代表二叉树的中序遍历序列。

输出:

对应每个测试案例,输出一行:

如果题目中所给的前序和中序遍历序列能构成一棵二叉树,则输出n个整数,代表二叉树的后序遍历序列,每个元素后面都有空格。

如果题目中所给的前序和中序遍历序列不能构成一棵二叉树,则输出”No”。

样例输入:
81 2 4 7 3 5 6 84 7 2 1 5 3 8 681 2 4 7 3 5 6 84 1 2 7 5 3 8 6
样例输出:
7 4 2 5 8 6 3 1 No

#include "string"
#include "vector"
#include "iostream"    
 
using namespace std;
int count_node;
typedef struct _Node
{
    int value;
    struct _Node *pRight;
    struct _Node *pLeft;
}Node;
 
int findPos(const vector &vec, int a)
{
    if (vec.size()==0)
        return -1;
    for (int i = 0; i < vec.size();i++)
    {
        if (vec[i]==a)
            return i;
    }
    return -2;
}
 
//Tips:
//int *a;int * &p = a;
//很容易理解,把 int * 看成一个类型,a就是一个整型指针,p 是a的别名,那么a与p就完全等同了
void ReBuildBST(const vector &preVec, const vector &midVec, Node *&proot)
{//注意:proot是引用,要不然函数返回会对proot的内容进行撤销
    if (preVec.size() == 0)
        return;
 
    proot = new Node;
    proot->value = preVec[0];//prestr[0]肯定是当前二叉树的根
    proot->pLeft = NULL;
    proot->pRight = NULL;
    count_node++;
 
    if (preVec.size() == 1)
        return;
     
    //因为是互不相同的数据,所以直接判断prevec中的每一个数据是否一定能在midvec找到即可
    for (int i = 0; i < preVec.size();i++)
    {
        bool flag = false;
        for (int j = 0; j < midVec.size();j++)
        {
            if (preVec[i] == midVec[j])
                flag = true;
        }
        if (flag==false)
            return;
    }
 
    int k = findPos(midVec,preVec[0]);
    vector preLeft(preVec.begin() + 1, preVec.begin() + k + 1);
    vector midLeft(midVec.begin(), midVec.begin() + k);
    ReBuildBST(preLeft, midLeft, proot->pLeft);
 
    vector preRight(preVec.begin()+ k + 1, preVec.end());
    vector midRight(midVec.begin()+ k + 1, midVec.end());
    ReBuildBST(preRight, midRight, proot->pRight);
}
 
void postOrder(Node * root)
{
    if (root != NULL){
        postOrder(root->pLeft);
        postOrder(root->pRight);
        cout << root->value<<" ";
    }
}
 
int main()
{
    int N = 0;
    while (cin >> N)
    {
        count_node = 0;
        vector preVec(N,0), midVec(N,0);
        for (int i = 0; i < N; i++)
            cin >> preVec[i];
         
        for (int i = 0; i < N; i++)
            cin >> midVec[i];
         
        Node *pRoot=NULL;
        ReBuildBST(preVec, midVec, pRoot);
        if (count_node == N)
        {
            postOrder(pRoot);
            cout << endl;
        }
        else
        {
            cout << "No" << endl;
        }
        count_node=0;
    }
}
/**************************************************************
    Problem: 1385
    User: EbowTang
    Language: C++
    Result: Accepted
    Time:10 ms
    Memory:1520 kb


题目1387:斐波那契数列

题目描述:

大家都知道斐波那契数列,现在要求输入一个整数n,请你输出斐波那契数列的第n项。斐波那契数列的定义如下:

输入:

输入可能包含多个测试样例,对于每个测试案例,

输入包括一个整数n(1<=n<=70)。

输出:

对应每个测试案例,

输出第n项斐波那契数列的值。

样例输入:
3
样例输出:
2

#include "vector"
#include "string"
#include "algorithm"
#include 
#include "stack"
#include  
 
using namespace std;
 
int main()
{
    int  n;
    while (cin>>n && n >=  1&& n <= 70) 
    {
        vector vec(71,0);
        vec[0] = 0;
        vec[1] = 1;
        for (int i = 2; i <= n; i++)
            vec[i] = vec[i - 1] + vec[i-2];
        cout << vec[n]<


题目1388:跳台阶

题目描述:

一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法。

输入:

输入可能包含多个测试样例,对于每个测试案例,

输入包括一个整数n(1<=n<=70)。

输出:

对应每个测试案例,

输出该青蛙跳上一个n级的台阶总共有多少种跳法。

样例输入:
5
样例输出:
8

#include "vector"
#include "string"
#include "algorithm"
#include 
#include "stack"
#include  
 
using namespace std;
 
//当n=1时,ans=1,当n=2时,ans=2
//当n=3时,ans=3,当n=4时,ans=5
//当n=5时,ans=8
//令跳到第i个台阶时的方法数为f(i)
//当我们确定选择下一步跳2时,方法数就是f(i-1)(此时步数i-1+2=i+1)
//当我们确定选择下一步跳1时,方法数就是f(i)
//显然两种选择都可以,所以f(i+1)=f(i)+f(i-1)
int main()
{
     int  n;
    while (cin >> n)
    {
        vector vec(n+1);
        vec[1] = 1;
        vec[2] = 2;
        for (int i = 3; i <= n; i++)
        {
            vec[i] = vec[i - 1] + vec[i-2];
        }
        cout << vec[n] << endl;
    }
    return 0;
}
/**************************************************************
    Problem: 1388
    User: EbowTang
    Language: C++
    Result: Accepted
    Time:10 ms
    Memory:1520 kb
****************************************************************/


题目1389:变态跳台阶

题目描述:

一只青蛙一次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级。求该青蛙跳上一个n级的台阶总共有多少种跳法。

输入:

输入可能包含多个测试样例,对于每个测试案例,

输入包括一个整数n(1<=n<=50)。

输出:

对应每个测试案例,

输出该青蛙跳上一个n级的台阶总共有多少种跳法。

样例输入:
6
样例输出:
32

#include "vector"
#include "string"
#include "algorithm"
#include 
#include "stack"
#include   
 
using namespace std;
 
//当n=1时,ans=1,当n=2时,ans=2
//当n=3时,ans=4,当n=4时,ans=8
//令跳到第i个台阶时的方法数为f(i)
//当我们确定选择下一步跳1时,方法数就是f(i)
//当我们确定选择下一步跳2时,方法数就是f(i-1)
//当我们确定选择下一步跳3时,方法数就是f(i-2)
//当我们确定选择下一步跳4时,方法数就是f(i-3)
//.......
//显然以上选择都可以,所以f(i+1)=f(i)+f(i-1)+...........
int main()
{
    int  n;
    while (cin >> n)
    {
        vector vec(n + 1);
        vec[0] = 1;
        vec[1] = 1;
        vec[2] = 2;
        for (int i = 3; i <= n; i++)
        {
            int k = i;
            while (k > -1)
                vec[i] += vec[k--];//计算f(i+1)=f(i)+f(i-1)+...........
        }
        cout << vec[n] << endl;
    }
    return 0;
}
/**************************************************************
    Problem: 1389
    User: EbowTang
    Language: C++
    Result: Accepted
    Time:10 ms
    Memory:1520 kb
****************************************************************/


题目1391:顺时针打印矩阵

题目描述:

输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字,例如,如果输入如下矩阵:

1 2 3 4

5 6 7 8

9 10 11 12

13 14 15 16

则依次打印出数字1,2,3,4,8,12,16,15,14,13,9,5,6,7,11,10.

输入:

输入可能包含多个测试样例,对于每个测试案例,

输入的第一行包括两个整数m和n(1<=m,n<=1000):表示矩阵的维数为m行n列。

接下来的m行,每行包括n个整数,表示矩阵的元素,其中每个元素a的取值范围为(1<=a<=10000)。

输出:

对应每个测试案例,输出一行,

按照从外向里以顺时针的顺序依次打印出每一个数字,每个数字后面都有一个空格。

样例输入:
4 41 2 3 45 6 7 89 10 11 1213 14 15 16
样例输出:
1 2 3 4 8 12 16 15 14 13 9 5 6 7 11 10 

#include "vector"
#include "string"
#include "algorithm"
#include 
#include "stack"
#include   
 
using namespace std;
 //参考自《剑指offer》
void printMatrixInCircle(int *matrix, int row, int column, int start)
{
    int endX = column - 1 - start;
    int endY = row - 1 - start;
 
    int i;
    //打印从左到右一行
    for (i = start; i <= endX; i++)
    {//从start开始到endx
        cout< start)
    {
        for (i = start + 1; i <= endY; i++)
        {
            cout << matrix[i*column + endX] << " ";
        }
    }
 
    //打印从右到左一行
    if (endY > start && endX > start)
    {
        for (i = endX - 1; i >= start; i--)
        {
            cout << matrix[endY*column + i] << " ";
        }
    }
 
    //打印从下到上一列
    if (endX > start && endY > start + 1)
    {
        for (i = endY - 1; i >= start + 1; i--)
        {
            cout << matrix[i*column + start] << " ";
        }
    }
 
 
}
 
void printMatrix(int *matrix, int row, int column)
{
    if (matrix == NULL || row <= 0 || column <= 0)
        return;
     
    int start = 0;
    while (row > start * 2 && column > start * 2)
    {
        printMatrixInCircle(matrix, row, column, start);
        start++;
    }
    cout << endl;
}
 
int main()
{
    int m=0, n=0;//行 列
    while (cin>>m>>n)
    {
        if (m <= 0 || n <= 0)
            break;
         
        int *matrix = new int[m*n];
        if (!matrix)
            exit(-1);
 
        for (int i = 0; i < m*n; i++)
            cin>>matrix[i];
         
        printMatrix(matrix, m, n);
        delete[] matrix;
        matrix = NULL;
    }
 
    return 0;
}
/**************************************************************
    Problem: 1391
    User: EbowTang
    Language: C++
    Result: Accepted
    Time:910 ms
    Memory:1520 kb
****************************************************************/



题目1393:合并两个排序序列

时间限制:2 秒

内存限制:32 兆

特殊判题:

提交:474

解决:174

题目描述:

输入两个递增的序列,输出合并这两个序列后的递增序列。

输入:

每个测试案例包括3行:

第一行为1个整数n(1<=n<=1000000)表示这两个递增序列的长度。

第二行包含n个整数,表示第一个递增序列。

第三行包含n个整数,表示第二个递增序列。

输出:

对应每个测试案例,输出合并这两个序列后的递增序列。

样例输入:
41 3 5 72 4 6 8
样例输出:
1 2 3 4 5 6 7 8


#include "vector"  
#include   
#include "fstream"
#include "algorithm"  
#include 
#include "string"
#include 
#include 
#include "map"
 
using namespace std;
 
int main()
{
    int n = 0;
    while (cin >> n, n > 0)
    {
        vector nums1(n,0);
        vector nums2(n,0);
        vector ans(2*n, 0);
        for (int i = 0; i < n; i++)
            cin >> nums1[i];
        for (int i = 0; i < n; i++)
            cin >> nums2[i];
 //这道题没做对,但是思路的确是这样的,不知道错在哪里!
        int g = 0, h = 0;
        int i = 0;
        for (; i < 2 * n; i++)
        {
            if (g == n || h == n)
                break;
            if (nums1[g] < nums2[h])
                ans[i] = nums1[g++];
            else if (nums1[g] > nums2[h])
                ans[i] = nums2[h++];
            else{
                ans[i] = nums1[g];
                g++; h++;
            }
        }
        if (g < n)
        {
            while (g < n)
                ans[i++] = nums1[g++];
        }
 
        if (h < n)
        {
            while (h < n)
                ans[i++] = nums2[h++];
        }
 
        for (int j = 0; j < i-1; j++)
            cout << ans[j] << " ";
 
        cout <



题目1398:移动次数

题目描述:

众所周知JOBDU旗下的JOBBALA公司是一家以个性、亲民著称的IT公司。在JOBBALA公司成立50周年的日子里,公司CEO组织全体员工登山旅游。按照往常的习惯,导游通常要求游客按照身高从低到高的顺序排好,但是考虑这次JOBBALA人数太多,排序很耗时间。因此,导游想了想,要求JOBBALA的员工可以随便排,但是必须保证队列的第一个是队列中最矮的,队列的最后一个是队列中最高的。例如:队列 { 1, 4, 3, 2, 2, 5} 就是符合的队列,{1, 4, 2, 3, 2, 5}也符合,而{2, 1, 2, 3, 4, 5}就是错的。请问对于任意的队列,最少要两两交换多少次,可以让其符合导游的要求?

输入:

输入有多组测试案例,每个测试案例为2行。

第一行包括一个整数n(2<=n<=200)表示人数,接下来一行包括n个整数a1, a2, …… an (1<=ai<=200) 表示n个员工初始的排列。

输出:

对应每个测试案例,按照导游的要求,输出最少需要两两交换的次数。

样例输入:
289 88455 88 1 2
样例输出:
13
提示:
案例2中,最少需要移动三次:(55 88 1 2) -> (55 1 88 2) -> (1 55 88 2) -> (1 55 2 88)

#include 
 
using namespace std;
 
int main(){
 
         int N,temp;
         while(cin>>N){
               int minimum=300,maximum=-300,minI,maxI;
 
               for(int i=1;i<=N;++i){
                       cin>>temp;
                       if(minimum>temp)
                             minimum=temp,minI=i;
                       if(maximum<=temp)
                             maximum=temp,maxI=i;
               }
 
               int result=minI-1+N-maxI;
               if(minI>maxI)  result--;
               cout<




题目1402:特殊的数

时间限制:2 秒

内存限制:2 兆

特殊判题:

提交:3203

解决:540

题目描述:

现在有n个数,其中有一些出现了一次,一些出现了两次,一些出现了很多次。现在要求你找出那些只出现一次的数,并按升序输出。

输入:

本题有多组case。

每个case有两行,第一行输入一个n,表示有n个数,1<= n <= 1000000。

第二行有n个数字。每个数字的大小范围[1, 1000000]。

输出:

每次输出有两行。

第一行输出一个整数,表示出现一次的数的个数。

第二行按升序输出出现次数为一次的数字,两个数字之间用空格隔开。

样例输入:
5
1 2 2 3 3
7
1 2 2 3 4 4 2
2
2 2
样例输出:
1
1
2
1 3
0
#include 
#include   
#include 
 
using namespace std;
//二进制数bits的长度为1000001
bitset<1000001> bits;//出现一次将被置1,再出现将被置零,始终保留并记录只出现一次的数
bitset<1000001> bits_assit;//出现过一次将被置1,再出现不做处理
 
//如果某一个数只出现一次,那么必定在其该位置的二进制位必定为1,否则为0
int main()
{
    int n;
    while (scanf("%d", &n) != EOF)
    {
        bits.reset();//全部置零
        bits_assit.reset();
        int count = 0;//统计出现一次的数的数量
        for (int i = 1, temp = 0; i <= n; i++)
        {
            scanf("%d", &temp);
            if (!bits_assit[temp])//如果第一次出现(此时temp位置的二进制位为0)
            {
                bits.set(temp);//将此temp位置的二进制位设为1
                bits_assit.set(temp);
                count++;
            }
            else if (bits_assit[temp])//如果已经出现过,将其位置的二进制位置零(总是保持出现过一次的才置1)
            {
                if (bits[temp])
                {
                    bits.reset(temp);//将此temp位置的二进制位设为0
                    count--;
                }
            }
        }
        bool first_time=true;
        printf("%d\n",count);
        if(!count){
            continue;
        }
        for(int i=1;i<=1000000;i++){
            if(bits[i]){
                if(first_time){
                    first_time=false;
                }else{
                    putchar(' ');
                }
                printf("%d",i);
            }
        }
        putchar('\n');
    }
    return 0;
}
/**************************************************************
    Problem: 1402
    User: EbowTang
    Language: C++
    Result: Accepted
    Time:1320 ms
    Memory:1764 kb
****************************************************************/





你可能感兴趣的:(C++,算法,数据结构,九度,ACM,九度OJ解题集,九度OJ解题报告)