一.翻转数组
翻转数组就是要把数组中的元素的顺序反过来,比如一个数组{1, 2, 3, 4, 5, 6, 7, 8, 9},翻转之后就是{9, 8, 7, 6, 5, 4, 3, 2, 1}
1.思路一:
另外创建数组,反向把元素填入新创建的数组中
数组是将元素按照顺序依次存放的,长度固定,所以如果想要让数组“翻转”的话,一种最简单的思路就是直接创建一个相同长度的新数组,然后遍历所有元素,从末尾开始依次反向填入就可以了
#include"iostream"
using namespace std;
int main(){
const int len = 10;
int arr[len] = {0, 1, 2, 3, 4, 5, 6 ,7, 8, 9};
// 答案数组
int ans[len];
for (int i = 0; i < len; i++) {
ans[len - i - 1] = arr[i];
}
for (int num : ans) {
cout << num << "\t";
}
};
2.思路二:
利用双指针,直接完成基于原数组的翻转
#include"iostream"
using namespace std;
int main(){
const int len = 10;
int arr[len] = {0, 1, 2, 3, 4, 5, 6 ,7, 8, 9};
// 利用双指针完成基于原数组的翻转
int head = 0, tail = len - 1;
while (head < tail) {
int temp = arr[head];
arr[head] = arr[tail];
arr[tail] = temp;
tail--;
head++;
}
for (int num : arr) {
cout << num << "\t";
}
};
二.检验幻方
幻方是数学上的一个问题,它让一组不同的数组构成一个方阵,并且每行、每列、每个对角线的所有数之和相等,比如最简单的三阶幻方就是把1~9的数字填到九宫格里,要求横看、竖看、斜看的和都是15
我们可以给定一个n*n的矩阵,也就是二维数组,然后判断它是否是一个幻方
#include"iostream"
using namespace std;
int main(){
const int n = 3;
int arr[n][n] = {
{4, 9, 2},
{3, 5, 7},
{8, 1, 6}
};
// 计算目标和
int target = (1 + n * n) * n / 2;
bool judge = true;
// 还可以使用双重循环同时检验每一行和每一列是否满足条件
/*
for (int i = 0; i < n; i++) {
int row = 0, line = 0;
for (int j = 0; j < n; j++) {
row += arr[i][j];
line += arr[j][i];
}
if (row != target || line != target) {
judge = false;
break;
}
}
*/
// 检查每一行都是否满足条件
for (int i = 0; i < n; i++) {
int sum = 0;
for (int j = 0; j < n; j++) {
sum += arr[i][j];
}
if (sum != target) {
judge = false;
break;
}
}
// 检查每一列是否满足条件
for (int i = 0; i < n; i++) {
int sum = 0;
for (int j = 0; j < n; j++) {
sum += arr[j][i];
}
if (sum != target) {
judge = false;
break;
}
}
// 检查对角线位置是否满足条件
int leftToright = 0, rightToleft = 0;
for (int i = 0; i < n; i++) {
leftToright += arr[i][i];
rightToleft += arr[i][n - 1 - i];
}
if (leftToright != target || rightToleft != target) {
judge = false;
}
// 输出结果
cout << "Given matrix" << (judge ? " is " : " isn't ") << n << " order magic square";
};
三.大整数相加
在我们的实际应用中可能会遇到非常大的整数,甚至超过long long的范围,这时候就需要用字符串对数据进行保存,然后进行计算
最简单的需求就是“大整数相加”,也就是给定两个字符串形式的非负大整数计算它们的和
我们的思路是把字符串按每个字符一一拆开,相当于遍历整数上的每一个数位,然后通过“乘10叠加”的方式将它们整合起来,也就是我们经常用的“竖式加法”
#include"iostream"
using namespace std;
int main(){
string num1 = "12564512567548545532464874545623145";
string num2 = "21542135442465214534212456652344154";
// 答案字符串
string ans;
int len1 = num1.size() - 1;
int len2 = num2.size() - 1;
// 是否进位
int carry = 0;
// 循环遍历,两数对齐进行相加
while (len1 >= 0 || len2 >= 0) {
// 两个数是否遍历完,若已完成则补0
int x = (len1 >= 0) ? (num1[len1] - '0') : 0;
int y = (len2 >= 0) ? (num2[len2] - '0') : 0;
int sum = x + y + carry;
carry = sum / 10;
ans += (sum % 10 + '0');
len1--;
len2--;
}
// 还需要对结果进行翻转
int i = 0, j = ans.size() - 1;
while (i < j) {
char temp = ans[i];
ans[i] = ans[j];
ans[j] = temp;
i++;
j--;
}
cout << num1 << " + " << num2 << " = " << ans;
};
四.旋转图像
旋转图像的需求在图片处理的过程中非常常见,我们知道对于计算机而言,图像就是一组像素点的集合,所以图像旋转的问题本质上就是一个二维数组的旋转问题
因此我们可以给定一个二维数组表示一个图像,然后对其进行旋转
#include"iostream"
using namespace std;
int main(){
const int n = 4;
// 将矩阵顺时针翻转90度
int arr[n][n] = {
{5, 1, 9, 11},
{2, 4, 8, 10},
{13, 3, 6 , 7},
{15, 14, 12, 16}
};
// 以对角线为对称轴,两边元素进行互换
for (int i = 0; i < n; i++) {
for (int j = 0; j <= i; j++) {
int temp = arr[i][j];
arr[i][j] = arr[j][i];
arr[j][i] = temp;
}
}
// 对每一行都进行前后翻转
for (int i = 0; i < n; i++) {
for (int j = 0; j < n / 2; j++) {
int temp = arr[i][j];
arr[i][j] = arr[i][n - j - 1];
arr[i][n - j - 1] = temp;
}
}
for (int i = 0; i < n; i++) {
for(int j = 0; j < n; j++) {
cout << arr[i][j] << "\t";
}
cout << endl;
}
};
五.旋转链表
链表是一种常见的数据结构,对于数组来说,我们可以通过下标访问每个元素,也能够做到如果想要翻转一个数组,只需要不停地把头尾元素互换即可
而链表并没有“下标”,所以想要访问元素的话就只能依次遍历,如果想要翻转一个链表,关键在于“next”指针需要反向
#include"iostream"
using namespace std;
struct ListNode {
int value;
ListNode* next;
};
int main(){
ListNode p5 = {5, nullptr};
ListNode p4 = {4, &p5};
ListNode p3 = {3, &p4};
ListNode p2 = {2, &p3};
ListNode p1 = {1, &p2};
ListNode* list = &p1;
ListNode* np = list;
while(np) {
cout << (*np).value << "->";
np = (*np).next;
}
cout << "NULL" << endl;
// 为了进行链表的翻转,我们需要定义两个指针,一个指向当前遍历的节点,另一个指向之前的节点
ListNode* curr = list;
ListNode* prev = nullptr;
while (curr) {
ListNode* temp = (*curr).next;
(*curr).next = prev;
prev = curr;
curr = temp;
}
ListNode* newList = prev;
np = newList;
while(np) {
cout << (*np).value << "->";
np = (*np).next;
}
cout << "NULL" << endl;
};