剑指Offer

大城市里の小女人 提交于 2019-12-28 15:59:25

题目描述
在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。

每行二分

class Solution {
public:
    bool Find(int target, vector<vector<int> > array) {
        for( int i = 0 ; i < array.size() ; i++ ){
            int len = array[i].size(); 
            int pos = lower_bound(array[i].begin(),array[i].end(),target)-array[i].begin();
            if( pos < len && target == array[i][pos] ) return true ;
        }
        return false;
    }
};

题目描述
请实现一个函数,将一个字符串中的每个空格替换成“%20”。例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy。

从后往前遍历,移动

class Solution {
public:
	void replaceSpace(char *str,int length) {
		int c = 0 ; 
        for( int i = 0 ; i < length ; i++ ){
        	if( str[i] == ' ' ){
        		c ++ ; 
        	} 
        }
        for( int i = length - 1;  i >= 0 ; i-- ){
        	if( str[i] != ' ' ) str[i+2*c] = str[i] ;
        	else{
                c-- ;
        		str[i+2*c] = '%';
        		str[i+2*c+1] = '2';
        		str[i+2*c+2] = '0';
        	}  
        }
	}
};

题目描述
输入一个链表,按链表从尾到头的顺序返回一个ArrayList。

用栈

class Solution {
public:
    vector<int> printListFromTailToHead(ListNode* head) {
        vector<int>a;
        stack<int>s ; 
        while( head ){
            s.push(head->val) ; 
            head = head -> next ;
        }
        int x ; 
        while( s.size() ){
            x = s.top() ;
            s.pop() ; 
            a.push_back(x) ;
        }
        return a ;
    }
};

题目描述
输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。

递归建立二叉树:
每次以前序序列第一个x为根,在中序中找到x,左边的为左子树中序序列,右边的为右子树的中序序列;
再将得到的左,右子树的前序,中序序列分别重复上述过程;

class Solution {
public:
	TreeNode* reConstructBinaryTree( vector<int> pre,vector<int> vin ) {
	if ( !pre.size() || !vin.size() ) {
		return NULL;
	}
	TreeNode* rt = new TreeNode(pre[0]);
	for (int i = 0; i < vin.size(); i++) {
		if ( vin[i] == pre[0]) {
				//[L,R)
			vector<int> p1( pre.begin()+1 , pre.begin()+i+1 ) ;
			vector<int> v1( vin.begin() , vin.begin() + i ) ;
			rt->left = reConstructBinaryTree( p1 , v1 );
			vector<int> p2( pre.begin()+i+1 , pre.end() ) ;
			vector<int> v2( vin.begin()+i+1 , vin.end() ) ;
			rt->right = reConstructBinaryTree( p2 , v2 );
			break;
		}
	}
	return rt;
}
};

题目描述
用两个栈来实现一个队列,完成队列的Push和Pop操作。 队列中的元素为int类型。

Push则直接放入stack1
Pop则将stack1中全放入2,再取stack2栈顶

class Solution
{
public:
    void push(int node) {
        stack1.push(node) ;
    }

    int pop() {
        if( !stack2.size() ){
             while( stack1.size() ){ 
                stack2.push(stack1.top()) ; 
                stack1.pop() ;
            }   
        }
        int tmp = stack2.top() ; stack2.pop() ; 
        return tmp ;
    }

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

题目描述
把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。
输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素。
例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。
NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。

class Solution {
public:
    int minNumberInRotateArray(vector<int> a) {
        if( !a.size() )  return 0 ;
        sort( a.begin() , a.end() );
        return a[0] ; 
    }
};

题目描述
大家都知道斐波那契数列,现在要求输入一个整数n,请你输出斐波那契数列的第n项(从0开始,第0项为0)。
n<=39

class Solution {
public:
    int Fibonacci(int n) {
        int a[50] ; 
        a[0] = 0 ;
        a[1] = 1 ;
        for( int i = 2 ; i <= 40 ; i++ ){
           a[i] = a[i-1] + a[i-2] ;  
        }
        return a[n] ; 
    }
};

题目描述
一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法(先后次序不同算不同的结果)。

递推:f[n] = f[n-1] + f[n-2]

class Solution {
public:
    int jumpFloor(int number) {
	int n1 = 2 ; 
	int n2 = 1 ;
	int ans = 0 ;
	if( number == 1 ) return 1 ;
	else if( number == 2 ) return 2 ;
	for( int i = 3 ; i <= number ; i++ ){
		ans = n2 + n1 ; 
		n2 = n1 ;
		n1 = ans ;
	}
	return ans ;
    
    }
};

题目描述
一只青蛙一次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级。求该青蛙跳上一个n级的台阶总共有多少种跳法。

方法一:
f[n] = f[n-1] + f[n-2] + … + f[1]
方法二:
f[n] = f[n-1] + f[n-2] + … + f[1]
f[n-1] = f[n-2] + f[n-3] + … + f[1]
相减:f[n] = 2*f[n-1]
故结果为2^(n-1)

class Solution {
public:
    int jumpFloorII(int number) {
	int ans = 2 ;
	if( number == 1 ) return 1 ;
	else if( number == 2 ) return 2 ;
	int res = 3 ;
	for( int i = 3 ; i <= number ; i++ ){
		ans = res + 1 ; 
		if( i != number ) res += ans;	
	}
	return res + 1 ;
    }
};
class Solution {
public:
    int jumpFloorII(int number) {
           return 1<<(number-1);
    }
};

题目描述
我们可以用2 * 1的小矩形横着或者竖着去覆盖更大的矩形。请问用n个2 * 1的小矩形无重叠地覆盖一个2*n的大矩形,总共有多少种方法?

n = 1 , 一种
n = 2 ,横,竖两种
n = 3,第3列竖着放,用1列,剩 n = 2,2种
第3列横着放,用了2列,剩 n = 1,1种。共3种
… n=k时,只需要管横竖怎么放,故f[k] = f[k-1] + f[k-2]

class Solution {
public:
    int rectCover(int n) {
        if( !n ) return 0;
        if( n == 1 ) return 1;
        if( n == 2 ) return 2;
        return rectCover( n - 1 ) + rectCover( n - 2 ) ; 
    }
};

题目描述
输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。

方法一:补码和移码关系
方法二:n&(n-1)->将最右边的1变为0
方法三:当做无符号数逻辑右移(补0)(有符号数负数补码右移补1)

int  NumberOf1(int n) {
   if( !n ) return 0 ;
   long long ans = (long long)n ;
   int c = 0 ;
   if( n < 0 ) ans += (1ll<<32) ;  //补码,移码
   while( ans ){
       if( ans & 1 ) c++ ;
       ans >>= 1 ;
   }
   return c ;
}
class Solution {
public:
int  NumberOf1(int n) {
   int c = 0 ;
   while( n ){
        c ++ ; 
        n &= (n-1);        //每次使最右1变为0
   }
   return c ;
}
};
int  NumberOf1(int n) {
   int c = 0 ;
   unsigned int ans = (unsigned int)n ; // Logical Shift Right (add 0)
   while( ans ){
        if( ans & 1 ) c ++ ; 
        ans >>= 1 ;
   }
   return c ;
}

题目描述
给定一个double类型的浮点数base和int类型的整数exponent。求base的exponent次方。

保证base和exponent不同时为0

class Solution {
public:
    double Power(double a, int b) {
        if( !a ) return 0 ;
        if( !b ) return 1 ;
        double res = 1.0 ; 
        int c = abs(b) ; 
        for( int i = 0 ; i < c ; i++ ){
            res = 1.0 * res * a ; 
        }
        if( b < 0 ) res = (double)1.0/res ;
        return res ; 
    }
};

题目描述
输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变。

类似插入排序

class Solution {
public:
    void reOrderArray(vector<int> &a) {
	    int len = a.size() ;
	    for( int i = 0 ; i < len ; i ++ ){
	    	if( !(a[i]&1) ) continue ;
	    	for( int j = i - 1 ; j >= 0 ; j-- ){
	    		if( !(a[j]&1) && (a[j+1]&1) ){
		    		swap(a[j+1],a[j]) ;
		    	}
		    }
	    }
    }
};

题目描述
输入一个链表,输出该链表中倒数第k个结点。

队列只存储k个值

/*
struct ListNode {
	int val;
	struct ListNode *next;
	ListNode(int x) :
			val(x), next(NULL) {
	}
};*/
class Solution {
public:
    ListNode* FindKthToTail(ListNode* Head, unsigned int k) {
        if( Head == NULL ) return Head ;
	    unsigned int c = 0 ;
	    queue<ListNode*>q ;
	    while( Head ){
	    	q.push(Head);
	    	if( c < k ) c ++ ;
		    else q.pop() ;
		    Head = Head -> next ; 
	    }
        return ( c < k ? NULL : q.front() ) ; 
    }
};

题目描述
输入一个链表,反转链表后,输出新链表的表头。

p 指向x左节点,(初始null)q指向x节点(初始头指针),cur指向x下一节点
遍历一遍,将链表反转

/*
struct ListNode {
	int val;
	struct ListNode *next;
	ListNode(int x) :
			val(x), next(NULL) {
	}
};*/
class Solution {
public:
    ListNode* ReverseList(ListNode* head) {
        if( head == NULL ) return head ; 
	    ListNode* p = NULL;
	    ListNode* cur = head -> next ;
	    ListNode* q = head; 
	    while( cur ){ 
	    	q -> next = p ;
	    	p = q ;
	    	q = cur ; 
	    	cur = cur -> next ;
	    }
	    q -> next = p ;
        return q ;
    }
};

题目描述
输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则。

归并
设置L指针为新的表头(初始指向H1,H2更小的那个)
遍历H2与H1,比较大小,H2小则插入H1前面;
H2大则移动H1
最后H2不空则链接到后面

/*
struct ListNode {
	int val;
	struct ListNode *next;
	ListNode(int x) :
			val(x), next(NULL) {
	}
};*/
class Solution {
public:
    ListNode* Merge(ListNode* H1, ListNode* H2){
        if( H1 == NULL && H2 == NULL ) return NULL ; 
        if( H1 == NULL ) return H2 ; 
        if( H2 == NULL ) return H1 ; 
        
        ListNode* pre = new ListNode(-1) ; //pre初始化
        ListNode* tmp  ; 
        ListNode* L ;
        
        if( H1 -> val < H2 -> val ){
            L = H1 ; 
        }else L = H2 ;
        
        while( H1 && H2 ){
            if( H2 -> val <= H1 -> val ){
                tmp = H2 -> next ;
                pre -> next = H2 ; 
                H2 -> next = H1 ;
                pre = H2 ;
                H2 = tmp ; 
            }else{
                pre = H1 ;
                H1 = H1 -> next ;
            }
        }
        if( H2 ){
            pre -> next = H2 ; 
        }
        return L ; 
    }
};
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!