• 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;
    }
    
  • 相关阅读:
    作业
    剑指Offer:链表中倒数第k个节点
    剑指Offer:反转链表
    剑指Offer:数值的整数次方
    剑指Offer:剪绳子Ⅰ和剪绳子Ⅱ
    剑指Offer:机器人的运动范围
    Linux下进程与线程的区别
    剑指Offer:调整数组顺序使奇数位于偶数前面
    剑指Offer:删除链表的节点
    剑指Offer:打印从1到最大的n位数
  • 原文地址:https://www.cnblogs.com/Luweir/p/14147357.html
Copyright © 2020-2023  润新知