数组与字符串

题目:二维数组中的查找

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

思路:找出二维数组的规律,从左下到右上查找最快。

提高:代码优化

class Solution {
public:
    bool Find(int target, vector<vector<int> > array) {

 int rowCount = array.size();
        int colCount = array[0].size();
        int i,j;
        for(i=rowCount-1,j=0;i>=0&&j<colCount;)
        {
            if(target == array[i][j])
                return true;
            if(target < array[i][j])
            {
                i--;
                continue;
            }
            if(target > array[i][j])
            {
                j++;
                continue;
            }
        }
        return false;
        
        
         int a = array[0].size() - 1;
        int b = array.size() - 1;
        int i = 0;
        if(a >= 0 && b >= 0)
        {
            while(array[b][i] != target)
            {
                if(array[b][i] > target)
                    --b;
                else if(array[b][i] < target)
                     ++i;
                if(b < 0 || i > a)
                    return false;
            }
        }
        else
            return false;
        return true;
    }
};

题目:替换空格

请实现一个函数,将一个字符串中的每个空格替换成“%20”。例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy。

思路:先统计空格数量,再从后往前移动,这样只需要移动一次

提高:代码优化

class Solution {
public:
	void replaceSpace(char *str,int length) {
        int i = 0, space_back = 0, alphabet_length = 0;
        while(str[i] != '\0')
        {
            ++alphabet_length;
            if(str[i] == ' ')
                ++space_back;
            ++i;
        }
        int new_length = alphabet_length + 2*space_back;
        //从后往前替换
        if(new_length > length)
                return ;       
        while(alphabet_length >= 0)
        {
           // new_length--; //长了一位
            if(str[alphabet_length] != ' ')
            {
                str[new_length--] = str[alphabet_length];
            }
            else
            {
                str[new_length--] = '0';
                str[new_length--] = '2';
                str[new_length--] = '%';
            }
            --alphabet_length;
        }
        str[new_length] = '\0';
	}
};

题目:调整数组顺序使奇数位于偶数前面

思路:一、用类似冒泡的方法逐个交换相邻的数,二、用一个新数组,分别将奇数和偶数加入

提高:代码优化,解题思想

class Solution {
public:
    void reOrderArray(vector<int> &array) {
        int flag = 0;
        for(int i = 0; i != array.size(); ++i)
        {
            for(int j = 1; j != array.size(); ++j)
            {
                if(array[j] % 2 == 1 && array[j - 1] % 2 == 0)
                {
                    flag = array[j];
                    array[j] = array[j-1];
                    array[j - 1] = flag;
                }
            }
        }
    }
};

题目:字符串的排列

输入一个字符串,按字典序打印出该字符串中字符的所有排列。例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba。

题目:数组中出现次数超过一半的数字

数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。如果不存在则输出0。

思路:若这个数组中有一个数字超过一半,则利用一个统计变量times,那么最后那个使times为正的数就是要求的数;若不存在超多一半的数字,则无意义。

提高:这是利用数组特点的解法,还可以利用算法来解

   int MoreThanHalfNum_Solution(vector<int> numbers) {
        
        int length = numbers.size();
        int time = 1;
        int result = numbers[0];
        
        
        for(int i = 1; i < length; ++i)
        {
            if(time == 0)
            {
                result = numbers[i];
                time = 1;
            }
            else if (result == numbers[i])
                ++time;
            else
                --time;
        }
        time = 0;
        for(int i = 0; i < length; ++i)
        {
            if(numbers[i] == result)
                ++time;
        }
        return (time > length / 2) ? result : 0;
}

题目:最小的k个数

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

思路:利用冒泡算法,只需要排k次,其他的排序算法需要排所有。

提高:有很多种排序方法都需要会写,还可以堆排序。

class Solution {
public:
    vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {
        int length = input.size();
        vector<int> ivec;
        if(k > length)
        {
            return ivec;
        }
        int a = 0;
        for(int i = 0; i < k; ++i)
        {
            for(int j = i; j < length; ++j)
            {
                if(input[j] < input[i])
                {
                    a = input[j];
                    input[j] = input[i];
                    input[i] = a;
                }
            }
            ivec.push_back(input[i]);
        }
        return ivec;
    }
};

题目:连续子数组的最大和

HZ偶尔会拿些专业问题来忽悠那些非计算机专业的同学。今天测试组开完会后,他又发话了:在古老的一维模式识别中,常常需要计算连续子向量的最大和,当向量全为正数的时候,问题很好解决。但是,如果向量中包含负数,是否应该包含某个负数,并期望旁边的正数会弥补它呢?例如:{6,-3,-2,7,-15,1,2,2},连续子向量的最大和为8(从第0个开始,到第3个为止)。给一个数组,返回它的最大连续子序列的和,你会不会被他忽悠住?(子向量的长度至少是1)

思路:需要用一个变量做参照,排除掉最后的负数。

提高:代码优化,用动态规划来计算

class Solution {
public:
    int FindGreatestSumOfSubArray(vector<int> array) {
        int length = array.size();
        if(array.size() == 0)
            return 0;
        int sum = array[0];
        int SUM = array[0];
        for(int i = 1; i < length; ++i)
        {
            if(sum >= 0)
            {
                sum += array[i];
                if(array[i] > 0)
                {
                    SUM = sum;
                }
            }
            else
            {
                if(sum < array[i])
                    sum = array[i];
            }
            if(sum > SUM)
                SUM = sum;
        }
        return SUM;
    }
};

题目:把数组排成最小的数

输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。例如输入数组{3,32,321},则打印出这三个数字能排成的最小数字为321323。

思路:先将数组里的数据进行排序,然后再排接

提高:代码优化(自己写一个自定义的排序)

class Solution {
public:
    static bool cmp(int a, int b)
    {
        string A = "";
        string B = "";
        A += to_string(a);
        A += to_string(b);
        B += to_string(b);
        B += to_string(a);
        return A < B;
    }
    string PrintMinNumber(vector<int> numbers) {
        string str;
        if(numbers.size() == 0)
            return str;
        sort(numbers.begin(), numbers.end(),cmp);
        for(int i = 0; i < numbers.size(); ++i)
        {
            str += to_string(numbers[i]);
        }
        return str;
    }
};

题目:第一个只出现一次的字符位置

在一个字符串(0<=字符串长度<=10000,全部由字母组成)中找到第一个只出现一次的字符,并返回它的位置, 如果没有则返回 -1(需要区分大小写)

思路:利用map进行统计,然后找出次数为1的字符位置。

提高:利用map的时间复杂度是多少?利用hash是多少?

class Solution {
public:
    int FirstNotRepeatingChar(string str) {
        map<char, int> ismap;
        if(str.size() == 0)
            return -1;
        for(int i = 0; i < str.size(); ++i)
        {
            ++ismap[str[i]];
        }
        for(int i = 0; i < str.size(); ++i)
            if(ismap[str[i]] == 1)
                return i;
        return -1;
    }
};

题目:数组中的逆序对

在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数P。并将P对1000000007取模的结果输出。 即输出P%1000000007

题目:数字在排序数组中出现的次数

统计一个数字在排序数组中出现的次数。

思路:找出该数字在数组中的两头,相减。

提高:代码优化

class Solution {
public:
    int GetNumberOfK(vector<int> data ,int k) {
        int times = 0;
        int length = data.size();
        int front = 0;
        int back = length - 1;
        int mid = 0;
        while(front <= back)
        {
            mid = (front + back) / 2;
            if(data[mid] < k)
            {
                front = mid + 1;
            }
            else
            {
                back = mid - 1;
            }
        }
        times = front;
        
        front = 0;
        back = length - 1;
        while(front <= back)
        {
            mid = (front + back) / 2;
            if(data[mid] <= k)
            {
                front = mid + 1;
            }
            else
            {
                back = mid - 1;
            }
        }
        return (back - times) + 1;
    }
};

题目:左旋转字符串

汇编语言中有一种移位指令叫做循环左移(ROL),现在有个简单的任务,就是用字符串模拟这个指令的运算结果。对于一个给定的字符序列S,请你把其循环左移K位后的序列输出。例如,字符序列S=”abcXYZdef”,要求输出循环左移3位后的结果,即“XYZdefabc”。是不是很简单?OK,搞定它!

思路:1、直接根据题目意思求解。2、用3次翻转的方法求解

提高:代码优化

class Solution {
public:
    string LeftRotateString(string str, int n) {
        string sr;
        if(str.size() == 0)
        {
            return sr; 
        }
        for(int i = n; i < str.size(); ++i)
        {
                sr += str[i];
        }
        for(int i = 0; i < n; ++i)
        {
            sr += str[i];
        }
        return sr;
        
        
        
        
        /*
        int len = str.length();
        if(0 == len || 0 == n)
        {
            return str;
        }
        string &temp = str;
        fun_Reversal(temp, 0, n - 1);
        fun_Reversal(temp, n, len - 1);
        fun_Reversal(temp, 0, len - 1);
        return str;
    }
    void fun_Reversal(string &str, int begin, int end)
    {
        char temp;
        while(begin < end)
        {
            temp = str[begin];
            str[begin] = str[end];
            str[end] = temp;
            begin++;
            end--;
        } */
    }
};

题目:翻转单词顺序列

牛客最近来了一个新员工Fish,每天早晨总是会拿着一本英文杂志,写些句子在本子上。同事Cat对Fish写的内容颇感兴趣,有一天他向Fish借来翻看,但却读不懂它的意思。例如,“student. a am I”。后来才意识到,这家伙原来把句子单词的顺序翻转了,正确的句子应该是“I am a student.”。Cat对一一的翻转这些单词顺序可不在行,你能帮助他么?

思路:先把单词整体翻转,然后根据空格再逐个翻转

提高:代码优化

 void fun_Reversal(string& str, int front, int back)
        {
            char a;
            while(front < back)
            {
                a = str[front];
                str[front] = str[back];
                str[back] = a;
                ++front;
                --back;
            }
        }
    
    string ReverseSentence(string str) {
        int length = str.size();
        int front = 0;
        int back = length - 1;
        if(length <= 1)
            return str;
        fun_Reversal(str, 0, back);    //从头到尾翻转
        
        for(int i = 0; i < length; ++i)
        {
            if(str[i] == ' ')
            {
                fun_Reversal(str, front, i - 1);
                front = i + 1;
            }
            if(i == back)
            {
                fun_Reversal(str, front, back);
            }
        }

        return str;
        
        /*
        int len = str.length() - 1;
        if(len <= 1)
        {
            return str;
        }
        fun_Reversal(str, 0, len);
        int begin = 0;
        int end = 0; 
        while(end <= len)
        {
            while(str[end] != ' ' && (end <= len))
            {
                end++;
            }
            fun_Reversal(str, begin, end - 1);
            begin = end + 1;
            end++;
        }
        return str;
    }
    void fun_Reversal(string &str, int begin, int end)
    {
        char temp;
        while(begin < end)
        {
            temp = str[begin];
            str[begin] = str[end];
            str[end] = temp;
            begin++;
            end--;
        } */
    }
};

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值