2021-5-10矩阵最小路径/判环/用栈实现队列/虚表实际存储方式和内容规则

主题:

日常刷算法题,今天涉及到的有:

  • 虚表的实际存储方式和内容规则
  • 算法题:矩阵的最小路径问题(动态规划实现)
  • 算法题:判断有没有环
  • 算法题:用栈来实现队列操作,以及优化

内容:

1 矩阵的最小路径问题(动态规划问题)

问题:给定一个 n * m 的矩阵 a,从左上角开始每次只能向右或者向下走,最后到达右下角的位置,
路径上所有的数字累加起来就是路径和,输出所有的路径中最小的路径和。
基本思路:
思路1:动态规划的状态转换:假设现在处于一个矩阵的元素上,这个元素对应位置
上的到右下角的最小路径应该是 这个点的值+min(右边的点的最小路径,下面的点的最小路径)
因此可以使用一个数组dp来对应于矩阵的每一个位置的元素,记录每一个对应的元素
的到达右下角的最小路径,然后输出dp[0][0]即可。需要用到递归
思路2:也是动态规划的状态转换,只是每一个dp对应的元素表示的是从左上角走到这个
元素的最小路径。最后输出dp[n-1][m-1]即可。想要做出这个dp,可以考虑,第一行只可以来
自左边,第一列只可以来自上面。dp[0][0]是一个定值。
dp值 = 这个点的值+min(左边的点的最小路径,上面的点的最小路径)
代码:

int solve(int i,int j)  //递归实现的 
{
    return dp[i][j] = matrix[i][j]+ i>=row||j>=collumn?0:min(solve(dp[i+1][j]),solve(dp[i],[j+1]); )
}
    
    
    int minPathSum(vector<vector<int> >& matrix) {
        // write code here
        int collumn = matrix[0].size();
        int row = matrix.size();
        int dp[row][collumn];
        memset(dp, 0, sizeof(dp));
        dp[0][0] = matrix[0][0];
        for(int i=1;i<row;i++)
        {
            dp[i][0] = matrix[i][0]+dp[i-1][0];
        }
        for(int i=1;i<collumn;i++)
        {
            dp[0][i] = matrix[0][i]+dp[0][i-1];
        }
        for(int i=1;i<row;i++)
        {
            for(int j=1;j<collumn;j++)
            {
                dp[i][j] = matrix[i][j]+min(dp[i-1][j], dp[i][j-1]);
            }
        }
        return dp[row-1][collumn-1];
    
    }

2 判断有没有环的问题:

**问题:**判断给定的链表中是否有环。如果有环则返回true,否则返回false。你能给出空间复杂度的解法么?
**解题思路:**当打一个结来作为来过的标记,当检测到这个结的时候,说明来过,发生了环

bool hasCycle(ListNode *head) {
        ListNode* p = head;
        ListNode* temp;
        while(1)
        {
            if(p==NULL)
            {
                return false;
            }
            else{
                if(p==p->next)
                {
                    return true;
                }
                else{
                    temp = p;
                    p = p->next;
                    temp->next = temp;
                }
            }
        }
    } 

3 两个栈来实现一个队列
基本思路:当push的时候,就在一个栈里面进行push就可
当pop的时候,需要将一个栈的内容腾到另外一个栈里面,然后pop,就会pop出原来最
后面的元素。再腾到第一个栈里面
优化思路:惰性优化:当pop后,先不急着腾到另外一个栈,如果下一个还是pop
那么直接pop就行。如果下一个不是pop,再进行腾。因此,再push的时候需要判断
如果是第二个栈有元素,说明处于惰性状态,进行转移,然后push,否则,直接push
当pop的时候,如果第二个栈有元素,直接pop,如果没有元素,转移,然后pop

void push(int node) {
        stack1.push(node);
    }

    int pop() {
        while(!stack1.empty())
        {
            stack2.push(stack1.top());
            stack1.pop();
        }
        int tem = stack2.top();
        stack2.pop();
        while(!stack2.empty())
        {
            stack1.push(stack2.top());
            stack2.pop();
        }
        return tem;
    }

private:
    stack<int> stack1;
    stack<int> stack2;
}; 

4 虚表的实际存储方式

表指针(如果有条件存在的话)会存在于堆或者栈,和数据成员存放在一起
虚表的内容存放于代码段之上,虚函数则存放于代码段。
当继承时,子类的虚函数 如果是重写了父类的虚函数的话,那么就会覆盖虚表中的条目
当没有重写父类的虚函数时,会加在虚表的后面。
继承时子类和父类都会有非虚函数,不会出现在虚表中,这些函数的调用会根据指针的对象类型来调用.当调用对象为父类的指针/引用/对象名 的时候,只可以看见父类的内容。不管其理论上可不可以访问。此时会编译器报错。

代码:

class A
{
	public:
	virtual int fun()
	{
		return 1;	
	}
	void show1()
	{
		cout<<"show1\n";
	}
};
class B:public A
{
	public:
	virtual void show2()
	{
		cout<<"show2\n";
	}
};

int main(){
	A a;
	cout<<sizeof(A)<<endl;   //输出8
	
	a.show1(); 
	B b;
	b.show2();
	
	A* ap = new B;
	//ap->show2();  //此时会出错,因为指针类型可以理解为“视角”,在A的视角上,看不见B的内容 
	    //编译器报错,即使把 
	B* bp = new B;
	bp->show1(); //
	bp->show2();  //都不会报错,因为B的视角更大,可以看见A的内容
	return 0;
	}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值