算法题一
题目描述:
给定一个包含红色、白色和蓝色,一共 n 个元素的数组,原地对它们进行排序,使得相同颜色的元素相邻,并按照红色、白色、蓝色顺序排列。
此题中,我们使用整数 0、 1 和 2 分别表示红色、白色和蓝色。
(使用常数空间的一趟扫描算法)
输入输出样例:
示例1:
输入:nums = [2,0,2,1,1,0]
输出:[0,0,1,1,2,2]
示例 2:
输入:nums = [2,0,1]
输出:[0,1,2]
示例 3:
输入:nums = [0]
输出:[0]
示例 4:
输入:nums = [1]
输出:[1]
思考:
本由题意知,本题只能用单层循环且不能开辟新的内存空间
遍历一边时,遇到 2 将其从最后开始放, 遇到 0 将其从前往后方,自然中间剩下 1 ,符合题意
源代码:
#include <iostream>
using namespace std;
int main() {
int a[100];
int n;
cin >> n;
for (int i = 0; i < n; i++) {
cin >> a[i];
}
int left = 0; //左侧存放 0
int right = n - 1; //右侧存放 2
for (int i = 0; i <= right; i++) {
if (a[i] == 0) {
a[i] = a[left]; //交换
a[left] = 0;
left++;
}
if (a[i] == 2) {
a[i] = a[right]; //交换
a[right] = 2;
right--;
i--; //避免 1被忽略
}
}
for (int i = 0; i < n; i++) {
cout << a[i];
}
return 0;
}
算法题二
题目描述:
请判断一个链表是否为回文链表。
(自己创建输入输出链表)
输入输出样例:
示例 1:
输入: 1->2
输出: false
示例 2:
输入: 1->2->2->1
输出: true
思考:
遍历链表,把每个节点的值储存在数组中,然后判断该数组是否回文
源代码:
#include <bits/stdc++.h>
using namespace std;
int a[10000];
typedef struct Node {
int data;
struct Node* next;
}node;
int main() {
int n, x;
cin >> x;
int xx = x;
node* head = (node*) malloc(sizeof(node)); //创建链表
head -> next = NULL;
node* p = head;
while (x--) {
cin >> n;
node* pnew = (node*) malloc(sizeof(node));
pnew -> data = n; //存入数据
pnew -> next = NULL;
p -> next = pnew;
p = pnew;
}
node* q = head -> next;
for (int i = 0; i < xx; i++) { //将链表的数据依次存入数组
a[i] = q -> data;
q = q -> next;
}
int xxx = xx - 1;
for (int i = 0; i < xxx; i++, xxx--) { //判断是否为回文
if (a[i] != a[xxx]) {
cout << "false";
return 0;
}
}
cout << "true";
return 0;
}
算法题三
题目描述:
给定一个只包括 ‘(’,’)’,’{’,’}’,’[’,’]’ 的字符串 s ,判断字符串是否有效。
有效字符串需满足:
1.左括号必须用相同类型的右括号闭合。
2.左括号必须以正确的顺序闭合。
输入输出样例:
示例 1:
输入:s = “()”
输出:true
示例 2:
输入:s = “()[]{}”
输出:true
示例 3:
输入:s = “(]”
输出:false
示例 4:
输入:s = “([)]”
输出:false
示例 5:
输入:s = “{[]}”
输出:true
思考:
栈先入后出特点恰好与本题括号排序特点一致,即若遇到左括号入栈,遇到右括号时将对应栈顶左括号出栈,则遍历完所有括号后 stack 仍然为空;
源代码:
class Solution {
public:
bool isValid(string s) {
stack<char> stk;
if(!s.size()) {
return true; //空串
}
else
{
for(int i = 0; i < s.size(); i++)
{
if (s[i] == '(' || s[i]=='[' || s[i]=='{') //左括号入栈
stk.push(s[i]);
else
{
if (stk.empty()) return false; //右括号时,栈空必定false
if (s[i] == ')' && stk.top() == '(') stk.pop(); //对号
else if (s[i]==']' && stk.top()=='[') stk.pop();
else if (s[i]=='}' && stk.top()=='{') stk.pop();
else return false; //对不上左括号,必定是false
}
}
if(stk.empty()) {
return true; //栈空,true
}
else return false; //栈非空,false
}
}
};
算法题四
题目描述:
一般的文本编辑器都有查找单词的功能,该功能可以快速定位特定单词在文章中的位置,有的还能统计出特定单词在文章中出现的次数。
现在,请你编程实现这一功能,具体要求是:给定一个单词,请你输出它在给定的文章中出现的次数和第一次出现的位置。注意:匹配单词时,不区分大小写,但要求完全匹配,即给定单词必须与文章中的某一独立单词在不区分大小写的情况下完全相同(参见样例1 ),如果给定单词仅是文章中某一单词的一部分则不算匹配(参见样例2 )。
输入输出样例:
示例 1:
输入:To
to be or not to be is a question
输出:2 0
示例 2:
输入:To
Did the Ottoman Empire lose its power at that time
输出:-1
思考:
对 b 数组即文本信息从头到尾扫一遍,对要找的单词和扫到符合条件的单词从第一个字母逐个判断是否相等
注意:得考虑文本开头就是空格的情况,还有单词中间是多个空格
源代码:
#include<iostream>
#include<cstring>
using namespace std;
int main() {
char a[11], b[1000001];
int i, j, lena, lenb, count = 0, min = 99999999, flag;
gets(a);
gets(b);
lena = strlen(a);
lenb = strlen(b);
for(i = 0;i < lenb;i++) { // 对b数组从头到尾扫一遍
if(i == 0 && b[i + lena] == ' ' || i == lenb-lena && b[lenb-lena-1] == ' ' || b[i-1] == ' ' && b[i+lena] == ' ') { //这里的判断是重点,在后面特别讲一下。
flag = 0;
for(j = 0;j < lena;j++) { //对要找的单词和扫到符合条件的单词从第一个字母逐个判断是否相等
if(a[j] != b[j+i] && a[j] != b[j+i]+32 && a[j] != b[j+i]-32) { //要么相等,要么互为大小写,若都不是
flag = 1; //则标记 为1
break;
}
}
if (flag == 0) { //如果没有被标记,则证明找到了要找的单词
count++;
if (min > i)
min = i; //第一次出现时i最小,记录下最小值i,即为他的位置
}
}
}
if (count == 0) //未找到,输出-1
cout << -1;
else //找到的情况
cout << count << " " << min;
return 0;
}
关于第一次 if 判断:
if(i == 0 && b[i + lena] == ' ' || i == lenb-lena && b[lenb-lena-1] == ' ' || b[i-1] == ' ' && b[i+lena] == ' ')
第一种情况:第一个字母在最开头且单词结尾为空格
第二种情况:在最后一个单词开头字母的位置为b的长度减去a的长度且单词前一位为空格
第三种情况:单词在中间时,它的左边和右边同时为空格
总结
这次考核算法题做得很烂,得继续加强对算法的训练,不能落下。像数据结构中的栈与队列(如本文中第三题所用到的思想),我一开始做这道题时就用错了方向。还有链表的复习与回顾没有做到位,继续努力。