初级算法(六)
1、引言
字符串
1、最长公共前缀:一个函数可以查找字符串数组中最长公共前缀,如果不存在则返回" "
单链表
1、删除链表中的某个节点
2、删除链表的倒数第N个节点
3、反转链表
2、最长公共前缀
要知道公共最长前缀的定义,这个前缀的字符串最重要的是连续的。采取默认字符串数组中的第一个字符串为公共最长的前缀。然后对第一个字符串进行不断截取。
/**
*
* @param strs 输入的字符串数组
* @return 返回的最长公共前缀
* 执行用时:0ms,内存消耗:39.2MB
*/
public String longestCommonPrefix(String[] strs) {
if(strs==null || strs.length==0)
return "";
//默认第一个为公共前缀
String pre=strs[0];
int i=1;
while(i<strs.length){
while(strs[i].indexOf(pre)!=0)
//只要返回值是不是第一个就一直进行截取
pre=pre.substring(0,pre.length()-1);
i++;
}
return pre;
}
3、删除链表中的某个节点
这个主要是看对于单链表的数据结构理解,单链表中的构成是一个数据域和指向下一个节点的指针。为此我们需要声明一个链表的对象。
public class ListNode{
int val;//存的是数据
ListNode next;//指向下一个节点的指针
ListNode(){
}
ListNode(int val){
this.val=val;
}
ListNode(int val,ListNode next){
this.val=val;
this.next=next;
}
}
删除具体节点,需要首先将该节点相邻的节点的值赋值给该节点,并将指针变化为相邻节点的下一个指针。没有涉及任何算法。
/**
* 删除链表中的某个节点
* @param node 被删除的节点,不能访问头节点
* 执行用时:0ms,内存消耗:41MB
*/
public void deleteNode(ListNode node) {
ListNode nextNode = node.next;//node下的一个节点是nextNode节点。
node.val=nextNode.val;
node.next=nextNode.next;
}
4、删除倒数第n个节点
这题首先需要计算单链表的长度,然后for循环遍历找到那个要删除的节点。这里我卡顿了一下,因为没弄懂Java的参数传递,Java的参数传递是值传递。就算是引用传递,参数传递则复制引用,因为改变了引用,所以原有的对象也会改变。这里调用length()方法,复制引用,但是其中的引用没有改变。因为单链表中的包含了next指针,指向下一个对象。
/**
*
* @param head 单链表
* @param n 倒数第n个节点
* @return 删除后的单链表
* 执行用时:0ms,内存消耗:39.4MB
*/
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode pre=head;
int length=length(head);
int last=length-n;
if(last==0)
return head.next;
for (int i = 0; i <last-1 ; i++) {//找到要删除的节点的位置
pre=pre.next;
}
pre.next=pre.next.next;
return head;
}
int length(ListNode head){//这里是引用中的引用,引用中的引用改变了,其值还是不会改变,因为Java是值传递
int length=0;
while(head!=null){
length++;
head=head.next;
}
return length;
}
5、反转链表
这题的一个解决办法,就是利用另外一个栈。利用栈的先进后出的原则。
/**
* 方法一:利用Java的栈结构的现金后出的原则
* @param head
* @return 反转后的单链表
* 执行用时1ms,内存消耗41.5MB
*/
public ListNode reverseList(ListNode head) {
int l=length(head);
if(l<=1)
return head;
Stack<ListNode> stack=new Stack<>();
while(head!=null){
stack.push(head);
head=head.next;
}
ListNode node=stack.pop();//弹出尾节点
ListNode dummy=node;//dummy则作为标记,标记新的单链表
while(!stack.isEmpty()){
ListNode tempNode=stack.pop();
node.next=tempNode;
node=node.next;
}
node.next=null;//将最后的尾节点的next的值设为null
return dummy;
}
还有一个解决办法就是使用双链表,但是这个双指针我没想到。
/**
* 方法2:双链表的求解
* 将原链表的节点,作为新链表的头节点
* @param head
* @return 反转后的单链表
*执行用时:0ms,内存消耗41.3MB
*/
public ListNode reverseList2(ListNode head) {
int l=length(head);
if(l<=1)
return head;
ListNode node=null;
while(head!=null){
//先保存访问节点的下一个节点
ListNode temp = head.next;
//将新链表的节点挂在原始链表的后面
head.next=node;
//更新链表
node=head;
//重新赋值,继续访问
head=temp;
}
return node;
}