剑指offer31-35

把数组排成最小的数

题目描述:输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。例如输入数组{3,32,321},则打印出这三个数字能排成的最小数字为321323。
题目分析:这道题我是不会的,这里只能拷贝一下别人的做法,利用了sort函数的特性。

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  answer="";
         sort(numbers.begin(),numbers.end(),cmp);
         for(int i=0;i<numbers.size();i++){
             answer+=to_string(numbers[i]);
         }
         return answer;
     }
 };

丑数

题目描述:把只包含质因子2、3和5的数称作丑数(Ugly Number)。例如6、8都是丑数,但14不是,因为它包含质因子7。 习惯上我们把1当做是第一个丑数。求按从小到大的顺序的第N个丑数。
题目分析:这个题最简单的方法当然是遍历求每个数,但这样做非常的傻,而且复杂度巨高无比,所以要利用丑数的性质来分析。

class Solution {
public://别人的代码就是精简,惭愧啊,继续学习。
	int GetUglyNumber_Solution(int n) {
        if (n == 0)return 0;
		if (n == 1)return 1;
		int ptwo = 0;
		int pthree = 0;
		int pfive = 0;
		vector<int>uglynum;
		uglynum.push_back(1);
		for (int i = 2; i <= n; i++) {
			if (uglynum[ptwo] * 2 <= uglynum[pthree] * 3 && uglynum[ptwo] * 2 <= uglynum[pfive] * 5) {      //X2最小
				uglynum.push_back(uglynum[ptwo] * 2);
				
				if (uglynum[ptwo] * 2 == uglynum[pthree] * 3) { pthree++; }
				if (uglynum[ptwo] * 2 == uglynum[pfive] * 5) { pfive++; }
				ptwo++;
				continue;
			}
			if (uglynum[pthree] * 3 <= uglynum[ptwo] * 2 && uglynum[pthree] * 3 <= uglynum[pfive] * 5) {     //X3最小
				uglynum.push_back(uglynum[pthree] * 3);
				if (uglynum[pthree] * 3 == uglynum[pfive] * 5) { pfive++; }
				pthree++;
				continue;
			}
			if (uglynum[pfive] * 5 <= uglynum[ptwo] * 2 && uglynum[pfive] * 5 <= uglynum[pthree] * 3) {       //X5最小
				uglynum.push_back(uglynum[pfive] * 5);
				pfive++;
				continue;
			}
		}
		int number = uglynum.size();
		return uglynum[number - 1];
	}
};

第一个只出现一次的字符

题目描述:在一个字符串(0<=字符串长度<=10000,全部由字母组成)中找到第一个只出现一次的字符,并返回它的位置, 如果没有则返回 -1(需要区分大小写).
题目分析:这个题如果用map做将超级简单,就是不知道面试官喜不喜欢这种方法,嘿嘿。

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

数组中的逆序对

题目描述:在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数P。并将P对1000000007取模的结果输出,题目保证输入的数组中没有的相同的数字。 即输出P%1000000007
题目分析:这道题一看就是一个炒鸡大的数,最简单的方法当然是用两个指针找,时间复杂度n2,这样就太麻烦了,因此准备考虑归并的方法解决这个问题。本质上和归并排序类似。

//数据量大,必须用long
class Solution {
public:
	long long mercycount(vector<int>&data, long low, long high) {
		long long count = 0;
		vector<int>temp;
		for (int k = low; k <= high; k++) {
			temp.push_back(data[k]);
		}
		int mid = (temp.size() - 1) / 2;
		int i = mid; int j = temp.size() - 1;
		int zhizhen = high;
		while (zhizhen >= low) {
			if (i < 0 && j >= mid) {
				data[zhizhen] = temp[j];
				j--;
				zhizhen--;
				continue;
			}
			if (j <= mid && i >= 0) {
				data[zhizhen] = temp[i];
				i--;
				zhizhen--;
				continue;
			}
			if (temp[i] <= temp[j]) {
				data[zhizhen] = temp[j];
				j--;
				zhizhen--;
				continue;
			}
			if (temp[i] > temp[j]) {
				data[zhizhen] = temp[i];
				count += j - mid;
				i--;
				zhizhen--;
				continue;
			}
		}
		return count;
	}

	long long  mercy(vector<int>&data, long low, long high) {
		if (low == high)return 0;
		int mid = (low + high) / 2;
		long long  pre = mercy(data, low, mid);
		long long  next = mercy(data, mid + 1, high);
		long long  cur = mercycount(data, low, high);
		return pre + next + cur;
	}
	int InversePairs(vector<int> data) {
		long long number = data.size();
		if (number <= 1)return 0;
		long long count = mercy(data, 0, number - 1);
		return count % 1000000007;
	}
};

两个链表的第一个工作节点

题目描述:输入两个链表,找出它们的第一个公共结点。
题目分析:这道题很简单,最简单的方法就是压入两个栈,然后最后一个相同的点就是公共节点。

/*
struct ListNode {
	int val;
	struct ListNode *next;
	ListNode(int x) :
			val(x), next(NULL) {
	}
};*/
class Solution {
public:
	ListNode* FindFirstCommonNode(ListNode* pHead1, ListNode* pHead2) {
		if (pHead1 == nullptr && pHead2 == nullptr)return pHead1;
		int number1 = 1;
		int number2 = 1;
		ListNode* p1 = pHead1;
		ListNode* p2 = pHead2;
		while (p1 != nullptr) {
			p1 = p1->next;
			number1++;
		}
		while (p2 != nullptr) {
			p2 = p2->next;
			number2++;
		}
		ListNode* longlist;
		ListNode* shortlist;
		int diffnumber;
		if (number1 >= number2) {
			longlist = pHead1;
			shortlist = pHead2;
			diffnumber = number1 - number2;
		}
		else {
			longlist = pHead2;
			shortlist = pHead1;
			diffnumber = number2 - number1;
		}
		for (int i = 0; i < diffnumber; i++) {
			longlist = longlist->next;
		}
		while (shortlist != nullptr && longlist != nullptr) {
			if (shortlist == longlist)return shortlist;
			shortlist = shortlist->next;
			longlist = longlist->next;
		}
		return nullptr;
	}
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值