继续做leetcode上数组题3

1.
Remove Element
Given an array and a value, remove all instances of that value in place and return the new length.

The order of elements can be changed. It doesn't matter what you leave beyond the new length.

解:这题比较简单,不多说
class Solution {
public:
    int removeElement(int A[], int n, int elem) {
        int result = 0;
        for (int i = 0; i < n; ++i)
            if (A[i] != elem)
                A[result++] = A[i];
        return result;
       
       
    }
};

2.

Next Permutation

  Total Accepted: 20160  Total Submissions: 79731 My Submissions

Implement next permutation, which rearranges numbers into the lexicographically next greater permutation of numbers.

If such arrangement is not possible, it must rearrange it as the lowest possible order (ie, sorted in ascending order).

The replacement must be in-place, do not allocate extra memory.

Here are some examples. Inputs are in the left-hand column and its corresponding outputs are in the right-hand column.
1,2,3 → 1,3,2
3,2,1 → 1,2,3
1,1,5 → 1,5,1


解: 这题,看题看了半天没明白什么意思。 背几个单词,permutation排列, lexicographically字典的, ascend 上升的。

解析:这里主要是从序列后入手,分增序和降序(包含=)的情形,分析两种情形的处理,增序较简单,直接交换最后两个即可,降序需找出降序序列长度(到it位置),把其前一个数(一定少于it)与序列中大于其且最小的数交换后,这样确定了it的前一位,然后把其后面的排成最小的数即可(增序排列)。


    void nextPermutation(vector<int> &num) { //首先应该确定从数列的末尾开始下手,末尾序列为增序还是降,边界条件是几个等

        if (num.size() <= 1) return;    //返回少于2的数列

        vector<int>::iterator it;

        vector<int>::iterator min = num.end() - 1;

        if (*min > *prev(min))               //这里判断末尾是增序(只要最后两个是增序就可,注意这里相等的情形也考虑,只是相等交换                 

                                                //不是下一个序列而已),交换二者即是下一个序列,否则就是降序,需找出其大小。

           { swap(*min, *prev(min));             //其实这个可以归为下面的情况,只是it指向最后一个元素,即降序序列长度为0

             return ;

           }

        for (it = prev(num.end()); it != num.begin(); --it) //找出降序序列的长度,再往前一个,就一定少于it指向处的值

        {

            if (*(it - 1) >= *it)        //这里一开始露了=号,就漏了相等的情形,如,5,1,1

            {

                continue;

            }

            else break;

        }

        if (it != num.begin())       //如果不是整个都是降序,则要把it前一个元素与降序序列中比其大的数中最小的那个交换位置

        {                            //这种方法对=适用,如,2,5,1,1。。it指向5,与2交换,排序2,1,1为1,1,2

            int gap = 99999;

            auto gapmin = it;

            for (auto p = it ; p != num.end(); ++p)

                {

                    if ((*(it - 1) < *p))     //因为是降序,这里可以精简,即找到最后一个比*(it - 1)大的元素即最小的

                    {

                        if (gap > (*p - *(it - 1)))

                          { gap = (*p -*(it - 1) );

                            gapmin = p;}

                    }

                    else break;

                }

            swap(*(it - 1),*gapmin);            //交换位置

            sort(it,num.end());                //交换后,把it后增序排序,这样可以保证其后组成的数为最小

           

        }

        else

            sort(num.begin(),num.end());     //如果整个都是降序,则下一个序列不存在,输出其增序序列。

    }


经过上述思路整理出,如下简洁代码:

void nextPermutation(vector<int> &num) {

        if (num.size() <= 1) return;

        vector<int>::iterator it;

        for (it = prev(num.end()); it != num.begin(); --it)    //另外prev是C++11的std空间内函数

        {

            if (*(it - 1) >= *it) continue;

            else break;

        }

        if (it != num.begin())

        {

            auto p = it;

            for (; p != num.end(); ++p)  //p如果定义在里面下面就用不了了

                {

                    if (*(it - 1) < *p) continue;

                    else break;

                }

            swap(*(it - 1),*prev(p));

            sort(it,num.end());        

        }

        else

            sort(num.begin(),num.end());

    }


3.

Permutation Sequence

  Total Accepted: 17631  Total Submissions: 79273 My Submissions

The set [1,2,3,…,n] contains a total of n! unique permutations.

By listing and labeling all of the permutations in order,
We get the following sequence (ie, for n = 3):

  1. "123"
  2. "132"
  3. "213"
  4. "231"
  5. "312"
  6. "321"

Given n and k, return the kth permutation sequence.

Note: Given n will be between 1 and 9 inclusive.


解:明显可以用到上面的,但上面的是vector<int>,所以一开始想字符和数字之间转换。

后来用上面的方式超时,参考答案后,思路基本是这样的,原本的序列 a1,a2,a3,a4,,,an; ,因为n个元素不重复且1~n排好序,建立副本a',假设求第k个序列,那么k个后a1由1变到2后面需要(n - 1)!个序列,所以求第k个时a1 = k/(n - 1)!;a1定了之后,可以把a1和a'中a1对应的数去掉了,然后再看a2,对a2来说,k2 = k % (n-1)!, a2 = k2/(n - 2)!, 抹掉a2对应的,依次类推,最后剩下的a'中的唯一未用的数,就是最后一位,原理是实际是变相计数,123456从后两位开始看看有几种变换方式来计数,另外,因为无重复,所以抹掉a'中的数不会再被用到,这样就可以删除剩最后一个数就是最后一位,否则不好确定最后一位。


引出来一个问题是,int -〉char ,(int 和char 是一样的,输出的时候是int就按int输出,如果是char就按char输出(从ansci码表中找出数字对应的字符),但是经常遇到的是想字符是‘5’,也想输出数字5,然后就出现了一个理论经常听说,但实际未操作的,然后出现了如下程序)

int main()

{

 //字符‘0’对应的ansci码是48

 int a = 5;

 char b = a + 48;

    cout <<" intnum to charnum: " << b << endl;

    char c = '3';

 int d = c - '0';

    cout <<"charnum to intnum: " << d << endl;

 char e = 3;

 int f = e;

 cout << "intchar is int: " << f << endl;

}


但是后来想到STL中有模版化的next_permutation();于是写了以下代码,但是对于比较大的,超时(input:8,8590)

class Solution {

public:

    string getPermutation(int n, int k) {

        string s(n,'0');

        for (int i = 0; i < n; ++i)

            s[i++] = i;

        for (int i = 0;i < k - 1; ++i)

            next_permutation(&s[0],&s[n]);

        return s;    

    }

};

按照参考,康拓编码的思想,想出如下代码,结果run time error

class Solution {

public:

     string kth_permutation(string ss, int k)

    {

        int n = ss.length();

        string S(ss);

        string result(n,'0'); //一开始没初始化,最后result一直为空

        int base = 1;

        for (int i = 1; i < n ; ++i)

            base *=i;

        --k;

        for (int i = 0; i < n - 1; ++i)

        {

            result[i] = S[k/base + i];

            S.erase(k/base + i, 1);  //要记得用过后的擦除,这样后面的S[0]为需要的

            base = base /(n - i - 1);

            k = k/base;

        }

        result[n - 1] = S[0];

        return result;

    }

    string getPermutation(int n, int k) {

        if (n == 1) return "1";

        string s(n,'0');

        for (int i = 0; i < n; ++i)

            s[i] += i + 1;

        return kth_permutation(s,k);

    }    

};

最后AC的结果:

class Solution {

public:

    string kth_permutation(string ss, int k)

 {

        int n = ss.length();

        string S(ss);

        string result(n,'0');

        int base = 1;

        for (int i = 1; i < n ; ++i)

            base *=i;

        --k;

        for (int i = n -1; i > 0 ; --i)

        {

            result[ n - i - 1] = S[k/base];

            S.erase(k/base,1);

            k %= base;

            base = base /i;

        }

        result[n - 1] = S[0];

        return result;

 }

 string getPermutation(int n, int k) {

        if (n == 1) return "1";

        string s(n,'0');

        for (int i = 0; i < n; ++i)

            s[i] += i + 1;

        return kth_permutation(s,k);

  }

};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值