题目描述 用两个栈来实现一个队列,完成队列的Push和Pop操作。 队列中的元素为int类型。
inStack用来暂存数据,outStack用来存放队列pop的数据,经过两次栈的存放顺序正好正过来。
import java.util.Stack;
public class Solution {
Stack<Integer> in = new Stack<Integer>();
Stack<Integer> out = new Stack<Integer>();
public void push(int node) {
in.push(node);
}
public int pop() throws Exception {
if(out.isEmpty())
while(!in.isEmpty())
out.push(in.pop());
if(out.isEmpty())
throw new Exception("quere is empty");
return out.pop();
}
}
题目描述 输入链表的第一个节点,从尾到头反过来打印出每个结点的值。
1.使用栈Stack
import java.util.ArrayList;
import java.util.Stack;
public class Solution {
public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
Stack<Integer> stack = new Stack<>();
while(listNode != null) {
stack.add(listNode.val);
listNode = listNode.next;
}
ArrayList<Integer> list = new ArrayList<>();
while(!stack.isEmpty()) {
list.add(stack.pop());
}
return list;
}
}
2.使用递归,时间复杂度较大
ArrayList<Integer> list = new ArrayList<>();
while(listNode != null) {
list.addAll(printListFromTailToHead(listNode.next));
list.add(listNode.val);
}
return list;
3.使用Collections的reverse方法
ArrayList<Integer> list = new ArrayList<>();
while(listNode != null) {
list.add(listNode.val);
listNode = listNode.next;
}
Collections.reverse(list);
return list;
4.使用链表头插法
ListNode head = new ListNode(-1);
while(listNode != null) {
ListNode min = listNode.next;
listNode.next = head.next;
head.next = listNode;
listNode = min;
}
ArrayList<Integer> list = new ArrayList<>();
head = head.next;
while(head != null) {
list.add(head.val);
head = head.next;
}
return list;
题目描述 请实现一个函数,将一个字符串中的空格替换成“%20”。例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy。
1.先遍历字符串,找到存在的空格,在字符串尾部填充空格,使其长度等于填充之后的长度 2.定义两个指针,分别指向新串和旧串末尾 3.从后向前遍历,依次重新setCharAt,这样不会改变p1指向的旧串的内容
复杂度:O(n) + O(1)
public class Solution {
public String replaceSpace(StringBuffer str) {
int old_len = str.length();
for(int i=0; i<old_len; i++) {
if(str.charAt(i) == ' ') {
str.append(" ");
}
}
int p1 = old_len - 1;
int p2 = str.length() - 1;
while(p2 >= 0 && p2 > p1) {
char c = str.charAt(p1--);
if(c == ' ') {
str.setCharAt(p2--, '0');
str.setCharAt(p2--, '2');
str.setCharAt(p2--, '%');
} else {
str.setCharAt(p2--, c);
}
}
return str.toString();
}
}
题目描述 在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
考虑一下的数组: [ [1, 2, 3, 4, 5], [2, 3, 4, 5, 6], [3, 4, 5, 6, 7], [4, 5, 6, 7, 8] [10, 12, 34, 54, 56] ]
从右上角开始找,因为矩阵中的数,左边的数比他小,下面的数比他大。
public boolean Find(int target, int[][] matrix) {
if (matrix == null || matrix.length == 0 || matrix[0].length == 0)
return false;
int rows = matrix.length, cols = matrix[0].length;
int r = 0, c = cols - 1; // 从右上角开始
while (r <= rows - 1 && c >= 0) {
if (target == matrix[r][c])
return true;
else if (target > matrix[r][c])
r++;
else
c--;
}
return false;
}
复杂度 O(M + N) + O(1)
标签(空格分隔): fabric blockchain
构建你的第一个网络(BYFN)场景提供了由两个组织组成的示例Hyperledger Fabric网络,每个组织持有2个peer节点,以及一个“solo”排序服务。
我们将使用cryptogen
工具为我们生成各种网络实体的加密材料(x509证书和签名密钥)。这些certificates证书是身份的代表,它们允许在我们的网络实体进行交流和交易时进行签名/验证身份验证。
Cryptogen消费一个包含网络拓扑的crypto-config.yaml
,并允许我们为组织和属于这些组织的组件生成一组证书和密钥。每个组织都配置了唯一的根证书(ca-cert)
,它将特定组件(peers和orders)
绑定到该组织。通过为每一个组织分配唯一的CA证书,我们正在模仿一个经典的网络其中一个Member将使用自己的Certificate Authority
(证书授权)。 Hyperledger Fabric中的Transactions和通信由实体的private key
(私钥,存储的文件名是 keystore)签名,然后通过public key
(公钥,存储的文件名是 signcerts)进行验证。
网络实体的命名约定如下 - “.”。 因此,使用我们的ordering node作为参考点,我们看到一个名为 - orderer.example.com的ordering node,它与Orderer的MSP ID绑定。
Name和Domain就是关于这个组织的名字和域名,这主要是用于生成证书的时候,证书内会包含该信息。而Template Count=2是说我们要生成2套公私钥和证书,一套是peer0.org2的,还有一套是peer1.org2的。
最后Users. Count=1是说每个Template下面会有几个普通User(注意,Admin是Admin,不包含在这个计数中)。
我们运行cryptogen
工具,生成的证书和密钥将被保存到名为crypto-config
的文件夹中。
crypto-config
的层级结构如下
目录/hyperledger/fabric-samples/first-network/crypto-config/ordererOrganizations/example.com的详细结构如下:
configtxgen tool用于创建4个配置工作: order的genesis block
, channel的channel configuration transaction
, * 以及两个anchor peer transactions
一个对应一个Peer组织。
order block
是一个ordering service的创世区块,channel transaction
文件在Channel创建的时侯广播给order(因为orderer负责创建Channel)。anchor peer transactions
,正如名称所示,指定了每个组织在此channel上的Anchor peer
。
首先,启动网络的命令:docker-compose -f docker-compose-cli.yaml up -d
如果想要查看网络的实时日志,就不要使用 -d 选项。启动后,会有6个 docker containers,如下图:
前面,我们在 Create a Channel Configuration Transaction 部分,使用 configtxgen工具创建了channel configuration transaction。 你可以重复该过程以创建其它channel configuration transaction,(使用相同或不同的configtx.yaml配置文件)。 然后,可以重复本节中定义的流程,在网络中建立其它Channel。
以下命令是Channel更新,它们将传播到Channel的定义。实质上,我们在channel’s genesis block的顶部添加额外的配置信息。请注意,我们没有修改生成块,而只是将 delta(增量) 添加到,定义anchor peers的链中。
应用程序通过Chaincode与区块链ledger进行交互。因此,我们需要在每个将执行并endorse我们的transactions的peer上,安装Chaincode,然后在Channel上实例化Chaincode。
注意,对于每个Chaincode名称和版本,只能安装一个版本的源代码(即不能安装一份代码的多个版本)。 源代码在peer的文件系统中,文件系统的上下文(或者文件名字)是Chaincode名称和版本,它是语言不可知的。 同样,实例化的Chaincode容器将反映peer上已安装的是哪个语言的源码。
Chaincode运行在一个受保护的Docker容器当中,与背书节点的运行互相隔离。Chaincode可通过应用提交的交易对账本状态初始化并进行管理。
一段chaincode通常处理由网络中的成员一致认可的业务逻辑,故我们很可能用“智能合约”来代指chaincode。一段chiancode创建的(账本)状态是与其他chaincode互相隔离的,故而不能被其他chaincode直接访问。不过,如果是在相同的网络中,一段chiancode在获取相应许可后则可以调用其他chiancode来访问它的账本。
每个chaincode程序都必须实现 chiancode接口(Chaincode interface) ,接口中的方法会在响应传来的交易时被调用。特别地,Init
(初始化)方法会在chaincode接收到instantiate
(实例化)或者upgrade
(升级)交易时被调用,进而使得chaincode顺利执行必要的初始化操作,包括初始化应用的状态;Invoke
(调用)方法会在响应invoke
(调用)交易时被调用以执行交易。
其他chaincode shim APIs中的接口被称为chaincode存根接口(ChaincodeSubInterface),用于访问及修改账本,并实现chaincode之间的互相调用。
mkdir -p $GOPATH/src/sacc && cd $GOPATH/src/sacc
touch sacc.go
内务处理(housekeeping)
。对于每一个chaincode,它都会实现预定义的chaincode接口,特别是Init和Invoke函数接口。所以我们首先为我们的chaincode引入必要的依赖。我们将在此引入chaincode shim package
和peer protobuf package
。
```
package mainimport ( “fmt”
"github.com/hyperledger/fabric/core/chaincode/shim"
"github.com/hyperledger/fabric/protos/peer" ) ``` - 初始化Chaincode ``` // Init is called during chaincode instantiation to initialize any data. func (t *SimpleAsset) Init(stub shim.ChaincodeStubInterface) peer.Response {
} ) ```