Algorithm:多维数组和矩阵


矩阵的题目,一般逻辑较为清晰,但实行起来比较复杂,需要考虑周到,特别是越界问题;

T 1:顺时针打印二维数组

这个问题看起来很容易,逻辑清晰,但实现起来还是复杂些,要考虑到不能重复打印,超出边界;

img

#include <iostream>
#include <vector>
using namespace std;

void printMatrix(vector<vector<int>> a)
{
	int leftuprow = 0, leftupcol = 0, rightdownrow = a.size()-1, rightdowncol = a[0].size()-1;
	while (leftuprow <= rightdownrow && leftupcol <= rightdowncol)
	{
		int r = leftuprow;
		int c = leftupcol;
		while (c <=rightdowncol)
		{
			cout << a[r][c++]<<" ";
		}
		c = rightdowncol;
		r = leftuprow+1;
		while (r <= rightdownrow)
		{
			cout << a[r++][c] << " ";
		}
		r = rightdownrow;
		c = rightdowncol - 1;
		while (c >= leftupcol)
		{
			cout << a[r][c--]<<" ";
		}
		c = leftupcol;
		r = rightdownrow - 1;
		while (r > leftuprow)
		{
			cout << a[r--][c] << " ";
		}
		leftupcol++;
		leftuprow++;
		rightdowncol--;
		rightdownrow--;
	}
}

int main()
{
	vector<vector<int>> test;
	for(int i=1;i<=12;i++)
	{
		vector<int> temp;
		while (i%4)
		{
			temp.push_back(i++);
		}
		temp.push_back(i);
		test.push_back(temp);
	}
	printMatrix(test);
	return 0;
}

T 2:将0所在的行列清零

如果矩阵中某个元素为0,则将其所在行和列清零;

img

可能会想到,我一边遍历矩阵,遇到0就将它所在行列全部清0;

但这样存在一个问题:如果某一行有多个0,遇到第一个0,会将本行和该列清0,那么循环遍历下去,这一行剩下的都是0,会将这些本不该清0的列都清0;

思路:把每个值为0的位置标记,最后统一对它们所在的行和列清0;

#include <iostream>
#include <vector>
using namespace std;

void setZero(vector<vector<int>> &a)
{
	vector<vector<int>> result;
	int lenRow=a.size(),lenCol=a[0].size();
    
	for(int i=0;i<lenRow;i++)
	{
		for(int j=0;j<lenCol;j++)
		{
			if(a[i][j]==0)
			{
				vector<int> temp;
				temp.push_back(i);
				temp.push_back(j);
				result.push_back(temp);
			}
		}
	}
	for(auto r:result)
	{
		int row=r[0],col=r[1];
		for(int i=0;i<lenCol;i++)
		{
			a[i][col]=0;
		}
		for(int i=0;i<lenRow;i++)
		{
			a[row][i]=0;
		}
	}
}

int main()
{
	vector<vector<int>> test;
	for(int i=1;i<=16;i++)
	{
		vector<int> temp;
		while (i%4)
		{
			temp.push_back(i++);
		}
		temp.push_back(i);
		test.push_back(temp);
	}
	test[1][2]=0;
	test[2][1]=0;

	setZero(test);
	
	for(auto a:test)
	{
		for(auto aa:a)
		{
			cout<<aa<<' ';
		}
		cout<<endl;
	}
	return 0;
}

T 3:Z字形打印

img

void Z(vector<vector<int>> &a)
{
	int r = 0, m = a.size();//m=最大行数
	int c = 0, n = a[0].size();//n=最大列数

	bool dir = true; //控制方向,true为向上,false为向下
	while (r < m && c < n)
	{
		//从左下到右上,走上坡
		if (dir)
		{
			cout << a[r][c] << ' ';
			if (r == 0 && c < n - 1) //到第一行,但未到列边界,只能往右走
			{
				dir = !dir;
				c++;
				continue;
			}
			else if (r < m - 1 && c == n - 1) //到最后一列,未到最后一行,只能向下走
			{
				dir = !dir;
				r++;
				continue;
			}
			else
			{
				r--;
				c++;
			}
		}
		else //相反,走下坡
		{
			cout << a[r][c] << ' ';
			if (c == 0 && r < m - 1) //到第一列,未到最后一行,只能往下走
			{
				dir = !dir;
				r++;
				continue;
			}
			else if (r == m - 1 && c < n - 1) //到最后一行,未到最后一列,只能向右走
			{
				dir = !dir;
				c++;
				continue;
			}
			else
			{
				r++;
				c--;
			}
		}
	}
}

T 4:子数组的最大累加和

给定一个数组,返回子数组的最大累加和;

如 a = {1,-2,3,5,-2,6,-1};所有的子数组中[3,5,-2,6]可以累加出最大的和12;

思路:若累加到当前数的和sum为负,那么比较sum和max,若sum比max大,则更新max,并中断此次累加操作(因为无论下个数next是正是负,sum+next都比next小),从下一个数开始累加;

若加到当前数的和sum为正,则继续累加下去,每次累加比较和max的大小;

int maxSubArray(vector<int> &nums)
{
    int len = nums.size();
    if (len == 0)
        return 0;

    int sum = 0, maxSum = nums[0];
    for (int i = 0; i < len; i++)
    {
        sum += nums[i];
        if (sum > maxSum)
            maxSum = sum;
        if (sum < 0)
        {
            sum = 0;
        }
    }
    return maxSum;
}

详情见Leetcode第53题:最大子序和

T 5:矩阵的乘法

image-20200607120125129

vector<vector<int>> mutMatrix(vector<vector<int>> m1, vector<vector<int>> m2)
{
	int n = m1.size();	  //矩阵1的行数
	int m = m1[0].size(); //矩阵1的列数,矩阵2的行数肯定和矩阵1的列数相同

	int p = m2[0].size(); //矩阵2的列数
	vector<vector<int>> result;
	for (int i = 0; i < n; i++)
	{
		vector<int> temp;
		for (int j = 0; j < p; j++)
		{
			int sum = 0;
			for (int k = 0; k < m; k++)
			{
				sum += m1[i][k] * m2[k][j];
			}
			temp.push_back(sum);
		}
		result.push_back(temp);
	}
	return result;
}
原文地址:https://www.cnblogs.com/Luweir/p/14147357.html