あなたほばかですか.
13、打印1到最大的n位数
打印1到最大的n位数,如n=3时打印1到999
思路:求出最大的n位数,然后依次打印,但当n十分大事会出问题。这里涉及到大数问题。
n = 2 num = 1 for i in range(n): num = num*10 for i in range(1,num): print i一个更完善的思路: 用字符串表示数字,进行进位,全排列递归输出,略复杂。
用字符串解决大数问题的思路大致如下:
字符串中的每个字符都是‘0’到‘9’之间的某个字符,用来表示数字中的一位。数字最大是n位,故需要一个n+1的字符串,最后一个为结束符号‘\0’。当实际数字不够n位的时候,在字符串的前半部分补0。如果在数字前面补0的话,就会发现n位所有十进制数其实就是n个从‘0’到‘9’的全排列。也就是说,把数字的每一位都从‘0’到‘9’排列一遍,就可以得到所有的十进制数。但是在打印的时候,数字排在前面的0不打印。
字符串中的每个字符都是‘0’到‘9’之间的某个字符,用来表示数字中的一位。数字最大是n位,故需要一个n+1的字符串,最后一个为结束符号‘\0’。当实际数字不够n位的时候,在字符串的前半部分补0。如果在数字前面补0的话,就会发现n位所有十进制数其实就是n个从‘0’到‘9’的全排列。也就是说,把数字的每一位都从‘0’到‘9’排列一遍,就可以得到所有的十进制数。但是在打印的时候,数字排在前面的0不打印。
可以参考大佬的代码:Python实现代码
14、在O(1)时间删除链表结点
思路:这个首先想到的是顺序查找,复杂度为O(n),但是不满足要求啊。
好的解决方案是这么个思路:
如果要删除结点i,先把i的下一个节点j的内容复制到i,然后把i的指针指向节点j的下一个节点。此时再删除节点j。如果删除的节点位于链表的尾部,则从链表的头节点开始,顺序遍历得到该节点的前序节点,并完成删除操作。如果链表中只有一个节点,此时删除节点后,还需要把链表的头节点设置为NULL。
还有一点需要注意,上述思路基于要删除的点存在在链表中,而我们需要O(n)的时间才能判断链表中是否有该节点。面试时要告诉面试官这个假设。
综上,进阶思路:
1、判断要删除的节点后是否有节点,若有节点,则将该节点内容复制到要删除的节点,并删除该节点
2、若链表中只有一个节点,则删除该节点
3、若要删除的节点后面没有节点(即该节点为最后一个),则遍历到该节点前一位并删除该节点
class ListNode: def __init__(self, x = None): self.val - x self.next = None def __del__(self): self.val = None self.next = None class Solution: def DeleteNode(self, pListHead, pToBeDeleted): if not pListHead or not pToBeDeleted: return None if pToBeDeleted.next != None: #如果要删除的节点后面不为空,则将下一个节点复制 pToBeDeleted.val = pToBeDeleted.next.val pToBeDeleted.next = pToBeDeleted.next.next pToBeDeleted.next.__del__() elif pListHead == pToBeDeleted: pToBeDeleted.__del__() pListHead.__del__() else: pNode = pListHead while pNode != pToBeDeleted: pNode = pNode.next pNode.next = None pToBeDeleted.__del__()代码来自于 https://blog.csdn.net/slibra_l/article/details/78151979
15、调整数组顺序使奇数位于偶数前面
输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变。
思路:首先送上我的low代码,没看懂书上牛逼的算法。。。
def reOrderArray(array): # write code here ji = [] ou = [] alle = [] x=[] for i in array: if i % 2 == 0: ou.append(i) ou.sort() else: ji.append(i) ji.sort() alle.append(ji) alle.append(ou) for i in alle: for j in i: x.append(j) return x
class Solution { public: void reOrderArray(vector<int> &array) { vector<int> result; int num=array.size(); for(int i=0;i<num;i++) { if(array[i]%2==1) result.push_back(array[i]); } for(int i=0;i<num;i++) { if(array[i]%2==0) result.push_back(array[i]); } array=result; } };
16、链表中倒数第K个结点
输入一个单向链表,输出该链表中倒数第k个结点。
思路:
两个指针,先让第一个指针和第二个指针都指向头结点,然后再让第一个指正走(k-1)步,到达第k个节点。然后两个指针同时往后移动,当第一个结点到达末尾的时候,第二个结点所在位置就是倒数第k个节点了。
# -*- coding:utf-8 -*- # class ListNode: # def __init__(self, x): # self.val = x # self.next = None class Solution: def FindKthToTail(self, head, k): # write code here l=[] while head!=None: l.append(head) head=head.next if k>len(l) or k<1: return return l[-k]
时间复杂度O(n),一次遍历即可 public class Solution { public ListNode FindKthToTail(ListNode head,int k) { ListNode pre=null,p=null; //两个指针都指向头结点 p=head; pre=head; //记录k值 int a=k; //记录节点的个数 int count=0; //p指针先跑,并且记录节点数,当p指针跑了k-1个节点后,pre指针开始跑, //当p指针跑到最后时,pre所指指针就是倒数第k个节点 while(p!=null){ p=p.next; count++; if(k<1){ pre=pre.next; } k--; } //如果节点个数小于所求的倒数第k个节点,则返回空 if(count<a) return null; return pre; } }
17、反转链表
递归的方法其实是非常巧的,它利用递归走到链表的末端,然后再更新每一个node的next 值 ,实现链表的反转。而newhead 的值没有发生改变,为该链表的最后一个结点,所以,反转后,我们可以得到新链表的head。
注意关于链表问题的常见注意点的思考:
1、如果输入的头结点是 NULL,或者整个链表只有一个结点的时候
2、链表断裂的考虑
# -*- coding:utf-8 -*- # class ListNode: # def __init__(self, x): # self.val = x # self.next = None class Solution: # 返回ListNode def ReverseList(self, pHead): # write code here if pHead==None or pHead.next==None: return pHead last = None while pHead: tmp = pHead.next pHead.next=last last = pHead pHead=tmp return last
/* struct ListNode { int val; struct ListNode *next; ListNode(int x) : val(x), next(NULL) { } };*/ class Solution { public: ListNode* ReverseList(ListNode* pHead) { //如果链表为空或者链表中只有一个元素 if(pHead==NULL||pHead->next==NULL) return pHead; //先反转后面的链表,走到链表的末端结点 ListNode* pReverseNode=ReverseList(pHead->next); //再将当前节点设置为后面节点的后续节点 pHead->next->next=pHead; pHead->next=NULL; return pReverseNode; } };
18、合并两个排序的链表
输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则。思路:
初始化两个链表头,其中一个表头用以记录两个单调递增链表比较后的结果,另一个用以返回结果。
用while循环:
①如果两个链表不为空,比较进行,并将小的那个赋给合并的链表头。小表头继续走一步,合并表头继续走一步。
②如果两个链表有其一为空,那么跳出循环,并将另一不为null的链表的后续部分赋给合并链表。
# -*- coding:utf-8 -*- # class ListNode: # def __init__(self, x): # self.val = x # self.next = None class Solution: # 返回合并后列表 def Merge(self, pHead1, pHead2): # write code here mergeHead = ListNode(0) p = mergeHead while pHead1 and pHead2: if pHead1.val >= pHead2.val: mergeHead.next = pHead2 pHead2 = pHead2.next else: mergeHead.next = pHead1 pHead1 = pHead1.next mergeHead = mergeHead.next if pHead1: mergeHead.next = pHead1 elif pHead2: mergeHead.next = pHead2 return p.next
递归版本
public ListNode Merge(ListNode list1,ListNode list2) { if(list1 == null){ return list2; } if(list2 == null){ return list1; } if(list1.val <= list2.val){ list1.next = Merge(list1.next, list2); return list1; }else{ list2.next = Merge(list1, list2.next); return list2; } }